自定义方形布局无法按预期工作

Kau*_* NP 5 android android-layout

我在使用时偶然发现了这个问题custom Square Layout:通过扩展布局并覆盖其onMeasure()方法,使尺寸=两个中的较小者(高度或宽度).

以下是自定义布局代码:

public class CustomSquareLayout extends RelativeLayout{


    public CustomSquareLayout(Context context) {
        super(context);
    }

    public CustomSquareLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomSquareLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public CustomSquareLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        //Width is smaller
        if(widthMeasureSpec < heightMeasureSpec)
            super.onMeasure(widthMeasureSpec, widthMeasureSpec);

            //Height is smaller
        else
            super.onMeasure(heightMeasureSpec, heightMeasureSpec);

    }
}
Run Code Online (Sandbox Code Playgroud)

自定义方形布局工作正常,直到自定义布局超出屏幕范围.应该有什么应该自动调整到屏幕尺寸,但不会发生.如下所示,CustomSquareLayout实际上延伸到屏幕下方(不可见).我期望的是onMeasure处理这个问题,并给出适当的测量结果.但事实并非如此.这里感兴趣的是,即使认为CustomSquareLayout行为奇怪,它的子布局都属于方形布局,总是放在左侧.

在此输入图像描述

<!-- XML for above image -->
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="300dp"
        android:text="Below is the Square Layout"
        android:gravity="center"
        android:id="@+id/text"
        />

    <com.app.application.CustomSquareLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/text"
        android:background="@color/colorAccent"             #PINK
        android:layout_centerInParent="true"
        android:id="@+id/square"
        android:padding="16dp"
        >
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"            #Note this
            android:background="@color/colorPrimaryDark"    #BLUE
            >
        </RelativeLayout>
    </com.app.application.CustomSquareLayout>

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

正常情况:( Textview在顶部)

在此输入图像描述

以下是我引用的一些链接:

希望onMeasure扩展布局时找到解决方案,使用或任何其他功能(这样即使某些扩展了自定义布局,Square属性仍然存在)

编辑1:为了进一步说明,显示了第一种情况的预期结果在此输入图像描述

编辑2:我给出了一个偏好onMeasure()或者这样的功能,因为需要在之前(渲染之前)确定布局规格(尺寸).否则,在组件加载后更改尺寸很简单,但不要求.

Che*_*amp 7

您可以通过在布局后检查"方形"来强制方形视图.将以下代码添加到onCreate().

final View squareView = findViewById(R.id.square);
squareView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        squareView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        if (squareView.getWidth() != squareView.getHeight()) {
            int squareSize = Math.min(squareView.getWidth(), squareView.getHeight());
            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) squareView.getLayoutParams();
            lp.width = squareSize;
            lp.height = squareSize;
            squareView.requestLayout();
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

这将强制重新测量和布局具有替换的指定大小的方形视图MATCH_PARENT.不是非常优雅,但它的工作原理.

在此输入图像描述

您还可以向自定义视图添加PreDraw侦听器.

onPreDraw

boolean onPreDraw()

在即将绘制视图树时要调用的回调方法.此时,树中的所有视图都已经过测量并给出了一个框架.客户端可以使用它来调整其滚动边界,甚至可以在绘制之前请求新的布局.

返回true以继续当前绘图传递,或返回false以取消.

在自定义视图中的每个构造函数中添加对初始化方法的调用:

private void init() {
    this.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
        @Override
        public boolean onPreDraw() {
            if (getWidth() != getHeight()) {
                int squareSize = Math.min(getWidth(), getHeight());
                RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) getLayoutParams();
                lp.width = squareSize;
                lp.height = squareSize;
                requestLayout();
                return false;
            }
            return true;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

XML可以如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="300dp"
        android:gravity="center"
        android:text="Below is the Square Layout" />

    <com.example.squareview.CustomSquareLayout
        android:id="@+id/square"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/text"
        android:background="@color/colorAccent"
        android:padding="16dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_centerInParent="true"
            android:background="@color/colorPrimaryDark" />
    </com.example.squareview.CustomSquareLayout>

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)