'Constraint Flow widget ignores max width attributes

I have multiple layouts that I want to display in a different location depending on screen size. If the screen is wide enough (tablet), I want the layouts to display horizontally then wrap down to the next row. If the screen is narrow (phone), I want the layouts to stack vertically.

The Constraint Flow widget works correctly for this when I supply a fixed layout_width.

I would like to change the layout of the child containers to be dynamic…up to a limit. Spreading out the contents of the containers is only useful up to a certain point. Basically, when displayed on a phone I want the size of the containers to adapt to the screen size. When displayed on a tablet or large phone/portrait, limit the width so that it doesn’t consume the entire screen.

To achieve this, I set android:layout_width="match_parent" and app:layout_constraintWidth_max="350dp". The behavior works correctly in other layout containers but not Constraint with the Flow widget. The Flow widget ignores the max width attributes and relies on the layout_width. The second layout containers is pushed off the screen to the right. The outline of the second layout can be seen in Android Studio when the mouse is hovered over it.

How do I achieve my objective of a dynamic layout size and placement?

Fixed width value works correctly.Max width attributes push the second panel off screen.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/layoutOne"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_blue_dark"
            android:maxWidth="350dp"
            android:minHeight="490dp"
            app:layout_constraintWidth_max="350dp" />

        <androidx.appcompat.widget.LinearLayoutCompat
            android:id="@+id/layoutTwo"
            android:layout_width="350dp"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_purple"
            android:minHeight="490dp" />

        <androidx.appcompat.widget.LinearLayoutCompat
            android:id="@+id/layoutThree"
            android:layout_width="350dp"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_red_dark"
            android:minHeight="490dp" />

        <androidx.appcompat.widget.LinearLayoutCompat
            android:id="@+id/layoutFour"
            android:layout_width="350dp"
            android:layout_height="wrap_content"
            android:background="@android:color/black"
            android:minHeight="490dp" />

        <androidx.constraintlayout.helper.widget.Flow
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:constraint_referenced_ids="layoutOne,layoutTwo,layoutThree,layoutFour"
            app:flow_horizontalStyle="packed"
            app:flow_verticalAlign="top"
            app:flow_wrapMode="chain"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            />
    </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>


Solution 1:[1]

This is how I solved it. In the onCreate(), read the width value that was originally set in the XML. If the layout width exceeds the screen width then the layout width is set to the screen width.
I tried setting matchConstraintMaxWidth programmatically but it doesn't work. The layouts don't flow/wrap.

DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams)myConstraintLayout.getLayoutParams();
if(displayMetrics.widthPixels < (int) layoutParams.width )
    layoutParams.width = displayMetrics.widthPixels;
myConstraintLayout.setLayoutParams(layoutParams);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1