固定宽高比视图

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

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

Solutions Collecting From Web of "固定宽高比视图"

我实现了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">