Search code examples
androidandroid-constraintlayout

Specify max constraint percentage on a view


Problem

Specify Max Constraint percentage for any view.

For example -

In a case below I have a 2 left views and 2 right views.

  • I want to constraint that right can acquire maximum of 50% percent of the entire width.
  • The left items holds precedence which means they can acquire as much space they like. So, if any of the left item is large enough it can shift right items and shrink them down.

I tried the following approach but this doesn't seem to work i.e when right1 or right2 text gets long enough it takes the preference and acquires more than 50% width.

Currently, constraint layout probably doesn't support this but is there any way to achieve this?

XML

<?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:id="@+id/section_item_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/left_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toTopOf="@id/left_2"
        app:layout_constraintEnd_toStartOf="@id/l_container"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="spread"
        tools:text="Leftsadasdasdadsdasdasdhsjakjdhaskkjdhdjakskjhkjdashkjddasdasdsaadsdasd1" />

    <TextView
        android:id="@+id/left_2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/l_container"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toStartOf="@id/left_1"
        app:layout_constraintTop_toBottomOf="@id/left_1"
        tools:text="Left2" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guide"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/right_barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="start"
        app:constraint_referenced_ids="l_container" />

    <LinearLayout
        android:id="@+id/l_container"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_min="wrap"
        app:layout_constraintWidth_max="wrap"
        app:layout_constraintWidth_percent="0.5">

        <TextView
            android:id="@+id/right_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="1"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toTopOf="@+id/right_2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_chainStyle="packed"
            tools:text="Right1"
            tools:visibility="visible" />

        <TextView
            android:id="@+id/right_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="end"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="@id/left_2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1"
            app:layout_constraintTop_toBottomOf="@+id/right_1"
            tools:text="Right2"
            tools:visibility="visible" />

    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Solution

  • I took some liberties to simplify the layout for this illustration, but you should be able to reconstruct your layout from the following.

    <androidx.constraintlayout.widget.ConstraintLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <TextView
            android:id="@+id/left_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constrainedWidth="false"
            app:layout_constraintEnd_toStartOf="@id/right_barrier"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="Not so long" />
    
        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/right_barrier"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="start"
            app:constraint_referenced_ids="right_1" />
    
        <TextView
            android:id="@+id/right_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constrainedWidth="true"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="1"
            app:layout_constraintStart_toEndOf="@id/right_barrier"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintWidth_max="wrap"
            app:layout_constraintWidth_percent="0.5"
            android:text="very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very " />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    which produces this:

    enter image description here

    Increasing the text length in left_1 causes the left view encroach into the right half of the screen.

    enter image description here

    layout_constrainedWidth and layout_constraintWidth_max are what's of interest in the layout.