如何在Flow ConstraintLayout中使子项具有相同的大小?

时间:2019-07-01 05:56:02

标签: android android-layout android-constraintlayout

我有一堆要在屏幕上水平分布的图块。对于大多数设备,它们在单个行上的显示范围太广,因此我想将ConstraintLayout与Flow帮助器一起使用。我可以解决这个问题。

但是我想确保每个瓦片的宽度相同。理想地,每个图块将与最宽的图块的所需宽度一样宽。确保Flow中的每个元素都具有相同宽度的正确方法是什么?

(我尝试创建链并使用layout_constraintHorizontal_weight,但这只是将每个图块挤压到同一行中,并阻止Flow流动。)

2 个答案:

答案 0 :(得分:0)

我最终添加了一个ViewTreeObserver,该ConstraintSet创建了一个Dynamically build case class or schema,该writing custom template filters [Django-doc]用于在布局发生之前设置子代的大小。它不是很漂亮,但是可以满足我的要求:

        final ConstraintLayout statContainer = findViewById(R.id.stat_container);

        statContainer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                try {
                    ConstraintSet constraintSet = new ConstraintSet();
                    constraintSet.clone(statContainer);

                    // Determine a minimum width
                    int width = 0;
                    for (int i = 0; i < statContainer.getChildCount(); i++) {
                        View child = statContainer.getChildAt(i);
                        if (child instanceof Flow) {
                            continue;
                        }

                        int candidateWidth = child.getMeasuredWidth();
                        width = Math.max(width, candidateWidth);
                    }

                    // Don't allow any child to get too big
                    int max = statContainer.getWidth() / 3;

                    width = Math.min(width, max);

                    // Set that width
                    for (int i = 0; i < statContainer.getChildCount(); i++) {
                        View child = statContainer.getChildAt(i);
                        if (child instanceof Flow) {
                            continue;
                        }
                        constraintSet.constrainWidth(child.getId(), width);
                    }

                    constraintSet.applyTo(statContainer);
                    statContainer.invalidate();

                } finally {
                    statContainer.getViewTreeObserver().removeOnPreDrawListener(this);
                }

                return false;
            }
        });

答案 1 :(得分:0)

仅使用Flow就可以为孩子们获得相同的宽度:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <View
        android:id="@+id/view1"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="#333" />

    <View
        android:id="@+id/view2"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="#333" />

    <View
        android:id="@+id/view3"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="#333" />

    <View
        android:id="@+id/view4"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:background="#333" />

    <androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        app:constraint_referenced_ids="view1,view2,view3,view4"
        app:flow_horizontalGap="8dp"
        app:flow_maxElementsWrap="2"
        app:flow_verticalGap="8dp"
        app:flow_wrapMode="chain"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

预览:

enter image description here

注意:该解决方案的一个缺点是,如果元素数量奇数,则最后一个元素将填满整个宽度。您可以在运行时以编程方式设置最后一个元素的宽度。