简单的方法来做dynamic,但方形布局

我使用一个GridView来显示一堆基本上是LinearLayouts的视图。 我希望LinearLayouts都是正方形的,但我也希望它们是dynamic大小的 – 也就是说,有两列,我希望LinearLayouts根据屏幕的大小进行伸展,但保持正方形。 有没有办法做到这一点通过xml布局,或者我必须设置高度和宽度编程?

对于正方形GridView项目的一个简洁的解决scheme是扩展RelativeLayoutLinearLayout并覆盖onMeasure如下所示:

 @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); } 

在xml中没有任何东西可以让你链接宽度和高度属性。 可能最简单的做法是将LinearLayout子类化并覆盖onMeasure

 @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int size = width > height ? height : width; setMeasuredDimension(size, size); } 

我用它来创build之前总是正方形的视图。 它应该仍然适用于LinearLayout

更多信息,这将有助于做到这一点: http : //developer.android.com/guide/topics/ui/custom-components.html http://developer.android.com/reference/android/view/View.MeasureSpec.html

我这样做了:

 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int size; if(widthMode == MeasureSpec.EXACTLY && widthSize > 0){ size = widthSize; } else if(heightMode == MeasureSpec.EXACTLY && heightSize > 0){ size = heightSize; } else{ size = widthSize < heightSize ? widthSize : heightSize; } int finalMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); super.onMeasure(finalMeasureSpec, finalMeasureSpec); } 

有了这个实现,你的布局将是正方形的,假设宽度和高度之间的尺寸较小。 甚至可以用dynamic值来设置,比如在LinearLayout中使用权重。

我们可以用一个非常简单的方法来做到这一点〜只需要调用super.onMeasure()两次〜

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = getMeasuredWidth(); int height = getMeasuredHeight(); int squareLen = width; if (height > width) { squareLen = height; } super.onMeasure(MeasureSpec.makeMeasureSpec(squareLen, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(squareLen, MeasureSpec.EXACTLY)); } 

我希望它能帮助你〜

答案可能迟了,但对新来的访问者会有所帮助。

在Android Studio 2.3中引入新的ConstraintLayout后 ,构build响应式布局现在非常容易。

在父级ConstraintLayout中,为了使其任何子级dynamic查看/布局,添加此属性

 app:layout_constraintDimensionRatio="w,1:1" 

w是指定宽度方向约束,1:1比例确保方形布局。

这是如此简单:

 public class SquareRelativeLayout extends RelativeLayout { public SquareRelativeLayout(Context context) { super(context); } public SquareRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SquareRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (widthMeasureSpec < heightMeasureSpec) super.onMeasure(widthMeasureSpec, widthMeasureSpec); else super.onMeasure(heightMeasureSpec, heightMeasureSpec); } } 

以下是适用于所有可以设置为查看或视图的布局参数的解决scheme:

  int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); int widthDesc = MeasureSpec.getMode(widthMeasureSpec); int heightDesc = MeasureSpec.getMode(heightMeasureSpec); int size = 0; if (widthDesc == MeasureSpec.UNSPECIFIED && heightDesc == MeasureSpec.UNSPECIFIED) { size = DP(defaultSize); // Use your own default size, in our case // it's 125dp } else if ((widthDesc == MeasureSpec.UNSPECIFIED || heightDesc == MeasureSpec.UNSPECIFIED) && !(widthDesc == MeasureSpec.UNSPECIFIED && heightDesc == MeasureSpec.UNSPECIFIED)) { //Only one of the dimensions has been specified so we choose the dimension that has a value (in the case of unspecified, the value assigned is 0) size = width > height ? width : height; } else { //In all other cases both dimensions have been specified so we choose the smaller of the two size = width > height ? height : width; } setMeasuredDimension(size, size); 

干杯

我的build议是创build一个从FrameLayoutinheritance的自定义布局类。 重写OnMeasure()方法,并把该SquareFrameLayout中的任何控件放置为方形。

这是如何在Xamarin.Android:

 public class SquareFrameLayout : FrameLayout { private const string _tag = "SquareFrameLayout"; public SquareFrameLayout(Android.Content.Context context):base(context) {} public SquareFrameLayout(IntPtr javaReference, Android.Runtime.JniHandleOwnership transfer):base(javaReference, transfer) {} public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs):base(context, attrs) {} public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs, int defStyleAttr):base(context, attrs, defStyleAttr) {} public SquareFrameLayout(Android.Content.Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes):base(context, attrs, defStyleAttr, defStyleRes) {} protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) { var widthMode = MeasureSpec.GetMode(widthMeasureSpec); int widthSize = MeasureSpec.GetSize(widthMeasureSpec); var heightMode = MeasureSpec.GetMode(heightMeasureSpec); int heightSize = MeasureSpec.GetSize(heightMeasureSpec); int width, height; switch (widthMode) { case MeasureSpecMode.Exactly: width = widthSize; break; case MeasureSpecMode.AtMost: width = Math.Min(widthSize, heightSize); break; default: width = 100; break; } switch (heightMode) { case MeasureSpecMode.Exactly: height = heightSize; break; case MeasureSpecMode.AtMost: height = Math.Min(widthSize, heightSize); break; default: height = 100; break; } Log.Debug(_tag, $"OnMeasure({widthMeasureSpec}, {heightMeasureSpec}) => Width mode: {widthMode}, Width: {widthSize}/{width}, Height mode: {heightMode}, Height: {heightSize}/{height}"); var size = Math.Min(width, height); var newMeasureSpec = MeasureSpec.MakeMeasureSpec(size, MeasureSpecMode.Exactly); base.OnMeasure(newMeasureSpec, newMeasureSpec); } } 

如果你想要一个视图(或任何其他控件)是正方形(和居中),只需将其添加到您的布局如下:

 <your.namespace.SquareFrameLayout android:id="@+id/squareContainer" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center"> <View android:id="@+id/squareContent" android:layout_width="match_parent" android:layout_height="match_parent" /> </your.namespace.SquareFrameLayout> 

查看SquareLayout ,这是一个为不同布局提供封装类的Android库 ,使它们的平方尺寸不会丢失任何核心function。

这些尺寸是在布局渲染之前计算的 ,因此一旦获得视图,就不需要重新渲染或者进行任何调整。

要使用库,请将其添加到您的build.gradle:

 repositories { maven { url "https://maven.google.com" } } dependencies { compile 'com.github.kaushikthedeveloper:squarelayout:0.0.3' } 

你需要的是SquareLinearLayout 。