固定宽高比视图

我将如何去执行一个固定的长宽比View ? 我想在GridView有1:1纵横比的项目。 我认为比GridView更好的子类GridView

编辑:我认为这需要以编程方式完成,这是没有问题的。 另外,我不想限制尺寸,只是纵横比。

  • Android:从视图中获取Viewgroup?
  • 以编程方式将片段添加到视图组
  • 将GestureDetector设置为所有子视图
  • Android视图和ViewGroup
  • 如何使用示例在android中创build自定义viewgroup
  • 使用dispatchDraw(Canvascanvas)
  • 揭秘Android构build过程
  • WindowManager中的全屏
  • 我实现了FixedAspectRatioFrameLayout,所以我可以重新使用它,并有任何托pipe视图与固定的长宽比:

     public class FixedAspectRatioFrameLayout extends FrameLayout { private int mAspectRatioWidth; private int mAspectRatioHeight; public FixedAspectRatioFrameLayout(Context context) { super(context); } public FixedAspectRatioFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } public FixedAspectRatioFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs); } private void init(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FixedAspectRatioFrameLayout); mAspectRatioWidth = a.getInt(R.styleable.FixedAspectRatioFrameLayout_aspectRatioWidth, 4); mAspectRatioHeight = a.getInt(R.styleable.FixedAspectRatioFrameLayout_aspectRatioHeight, 3); a.recycle(); } // **overrides** @Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) { int originalWidth = MeasureSpec.getSize(widthMeasureSpec); int originalHeight = MeasureSpec.getSize(heightMeasureSpec); int calculatedHeight = originalWidth * mAspectRatioHeight / mAspectRatioWidth; int finalWidth, finalHeight; if (calculatedHeight > originalHeight) { finalWidth = originalHeight * mAspectRatioWidth / mAspectRatioHeight; finalHeight = originalHeight; } else { finalWidth = originalWidth; finalHeight = calculatedHeight; } super.onMeasure( MeasureSpec.makeMeasureSpec(finalWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(finalHeight, MeasureSpec.EXACTLY)); } } 

    对于新用户,这是一个更好的非代码解决scheme:

    Android SDK v22中有一个名为Percent Support Library的新支持库(MinAPI是7我认为,不确定):

    src: android-developers.blogspot.in

    百分比支持库提供了基于百分比的维度和利润率,并且在这个版本中新增了通过app:aspectRatio设置自定义长宽比的function。 通过仅设置一个宽度或高度并使用aspectRatio,PercentFrameLayout或PercentRelativeLayout将自动调整另一个维度,以便布局使用设置的宽高比。

    要包括添加到您的build.gradle

     compile 'com.android.support:percent:23.1.1' 

    现在用PercentRelativeLayout / PercentFrameLayout包装你的视图(需要是正方形):

     <android.support.percent.PercentRelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView app:layout_aspectRatio="100%" app:layout_widthPercent="100%"/> </android.support.percent.PercentRelativeLayout> 

    你可以在这里看到一个例子。

    我最近为这个问题做了一个帮手类,写了一篇关于它的博客文章 。

    代码的肉如下:

     /** * Measure with a specific aspect ratio<br /> * <br /> * @param widthMeasureSpec The width <tt>MeasureSpec</tt> passed in your <tt>View.onMeasure()</tt> method * @param heightMeasureSpec The height <tt>MeasureSpec</tt> passed in your <tt>View.onMeasure()</tt> method * @param aspectRatio The aspect ratio to calculate measurements in respect to */ public void measure(int widthMeasureSpec, int heightMeasureSpec, double aspectRatio) { int widthMode = MeasureSpec.getMode( widthMeasureSpec ); int widthSize = widthMode == MeasureSpec.UNSPECIFIED ? Integer.MAX_VALUE : MeasureSpec.getSize( widthMeasureSpec ); int heightMode = MeasureSpec.getMode( heightMeasureSpec ); int heightSize = heightMode == MeasureSpec.UNSPECIFIED ? Integer.MAX_VALUE : MeasureSpec.getSize( heightMeasureSpec ); if ( heightMode == MeasureSpec.EXACTLY && widthMode == MeasureSpec.EXACTLY ) { /* * Possibility 1: Both width and height fixed */ measuredWidth = widthSize; measuredHeight = heightSize; } else if ( heightMode == MeasureSpec.EXACTLY ) { /* * Possibility 2: Width dynamic, height fixed */ measuredWidth = (int) Math.min( widthSize, heightSize * aspectRatio ); measuredHeight = (int) (measuredWidth / aspectRatio); } else if ( widthMode == MeasureSpec.EXACTLY ) { /* * Possibility 3: Width fixed, height dynamic */ measuredHeight = (int) Math.min( heightSize, widthSize / aspectRatio ); measuredWidth = (int) (measuredHeight * aspectRatio); } else { /* * Possibility 4: Both width and height dynamic */ if ( widthSize > heightSize * aspectRatio ) { measuredHeight = heightSize; measuredWidth = (int)( measuredHeight * aspectRatio ); } else { measuredWidth = widthSize; measuredHeight = (int) (measuredWidth / aspectRatio); } } } 

    我已经使用并喜欢杰克·沃顿(Jake Wharton)对ImageView的实现(对于其他视图应该类似),其他人也可能喜欢:

    AspectRatioImageView.java – 尊重应用于特定度量的宽高比的ImageView

    好的,它已经在xml中风格化了。

    为了不使用第三方解决scheme,并且考虑到在26.0.0中不赞成使用PercentFrameLayout和PercentRelativeLayout,我build议您考虑使用ConstraintLayout作为网格项目的根布局。

    您的item_grid.xml可能如下所示:

     <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/imageview_item" android:layout_width="0dp" android:layout_height="0dp" android:scaleType="centerCrop" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintDimensionRatio="H,1:1" /> </android.support.constraint.ConstraintLayout> 

    结果你得到这样的东西:

    固定比例大小的网格物品

    只需重写onSizeChanged并计算比率。

    公式的长宽比是:

     newHeight = original_height / original_width x new_width 

    这会给你这样的东西:

      @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //3:5 ratio float RATIO = 5/3; setLayoutParams(new LayoutParams((int)RATIO * w, w)); } 

    希望这可以帮助!

    我用TalL的答案创build了一个布局库。 随意使用它。

    RatioLayouts

    安装

    将其添加到文件的顶部

     repositories { maven { url "http://dl.bintray.com/riteshakya037/maven" } } dependencies { compile 'com.ritesh:ratiolayout:1.0.0' } 

    用法

    在布局的根视图上定义'app'命名空间

     xmlns:app="http://schemas.android.com/apk/res-auto" 

    将此库包含在您的布局中

     <com.ritesh.ratiolayout.RatioRelativeLayout android:id="@+id/activity_main_ratio_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:fixed_attribute="WIDTH" // Fix one side of the layout app:horizontal_ratio="2" // ratio of 2:3 app:vertical_ratio="3">