简单的方法来做动态但方形的布局

Cat*_*ine 78 android

我正在使用a GridView来显示一堆本质上的视图LinearLayouts.我希望LinearLayouts它们都是方形的,但我也希望它们是动态大小的 - 也就是说,有两列我希望LinearLayouts根据屏幕的大小进行拉伸但保持方形.有没有办法通过xml布局来做到这一点,还是我必须以编程方式设置高度和宽度?

jda*_*mcd 111

方形GridView项目的一个简洁的解决方案是扩展RelativeLayoutLinearLayout覆盖,onMeasure如下所示:

@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果它将Math.min(widthMeasureSpec,heightMeasureSpec)的值传递给super.onMeasure()的两个参数,则会更灵活. (4认同)
  • 正如@DavidMerriman上面所说,如果视图宽度高于高视图,这将导致视图延伸到查看区域下方,从而切断部分视图. (3认同)
  • 这是使用度量规范而不是使用setMeasuredDimension(),这样就很好了.但它不是很灵活,因为它总是需要宽度. (2认同)

小智 53

回答可能会迟到但仍然会对新访客有所帮助.

借助Android Studio 2.3中引入的新ConstraintLayout,现在可以非常轻松地构建响应式布局.

在父ConstraintLayout中,要使其任何子视图/布局动态平方,请添加此属性

app:layout_constraintDimensionRatio="w,1:1"
Run Code Online (Sandbox Code Playgroud)

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

  • 这是王者的答案 (7认同)
  • 确保在子布局中为布局宽度和高度设置"0dp".否则它将无法工作. (5认同)

Dav*_*man 42

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);
}
Run Code Online (Sandbox Code Playgroud)

我用它来创建以前总是正方形的视图.它应该仍然适用于LinearLayout.

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

  • 别忘了添加:`super.onMeasure(widthMeasureSpec,widthMeasureSpec);`! (3认同)

Fer*_*rgo 42

我这样做了:

@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);
}
Run Code Online (Sandbox Code Playgroud)

通过此实现,您的布局将是正方形,假设宽度和高度之间的尺寸较小.它甚至可以设置动态值,例如在LinearLayout中使用权重.


pas*_*whu 10

我们可以用一种非常简单的方式完成它 - 只需调用super.onMeasure()两次.

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int width = getMeasuredWidth();
    int height = getMeasuredHeight();
    int squareLen = Math.min(width, height);

    super.onMeasure(
        MeasureSpec.makeMeasureSpec(squareLen, MeasureSpec.EXACTLY), 
        MeasureSpec.makeMeasureSpec(squareLen, MeasureSpec.EXACTLY));
}
Run Code Online (Sandbox Code Playgroud)

通过调用super.onMeasure()两次,这在绘制过程方面效率较低,但这是修复其他答案可能导致的布局问题的简单方法.

  • 而不是两次调用super.onMeasure,第二次只需要调用setMeasuredDimension(squareLen,squareLen); (2认同)

Abd*_*sae 5

它很简单:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)