testivanivan
testivanivan

Reputation: 1514

Android. ConstraintLayout: constraint end not working

I need to create chain with ConstraintLayout.I want the TextView to be attached to the left side, the text is immediately followed by a ImageView, and another ImageView is attached to the right side of the screen. See an example.

enter image description here

If the TextView contains long text, I need the text to go to another line. That is, so that the TextView does not overlap with the image view on the right, but is limited to margin. See an example.

enter image description here

Here is my code:

<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="wrap_content"
    tools:ignore="MissingPrefix">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/text"
        android:textColor="@color/black"
        android:textSize="@dimen/text_size_14"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0" />

    <ImageView
        android:id="@+id/ivFirst"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="16dp"
        android:src="@drawable/ic_first"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/ivSecond"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintStart_toEndOf="@id/tvTitle"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0" />

    <ImageView
        android:id="@+id/ivSecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_second"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0" />
</androidx.constraintlayout.widget.ConstraintLayout>

If the text is not long, then everything works well, but if the text is long, then it is superimposed on the ImageView and goes beyond the screen. I tried to use chain but nothing worked. Please, help me.

Upvotes: 1

Views: 2313

Answers (3)

Zain
Zain

Reputation: 40908

You can use FlexboxLayout to wrap the tvTitle TextView & the ivFirst ImageView; So that it controls to wrap the content of the TextView to the next line and avoid pushing the ivFirst to the right/end.

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <com.google.android.flexbox.FlexboxLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        app:alignContent="center"
        app:alignItems="center"
        app:flexDirection="row"
        app:flexWrap="nowrap"
        app:layout_constraintBottom_toBottomOf="@+id/ivSecond"
        app:layout_constraintEnd_toStartOf="@+id/ivSecond"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/tvTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/text"
            android:textColor="@color/black"
            android:textSize="@dimen/text_size_14"
            app:layout_flexShrink="10000" />

        <ImageView
            android:id="@+id/ivFirst"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_first"
            android:layout_marginStart="8dp"
            android:layout_marginEnd="16dp"/>

    </com.google.android.flexbox.FlexboxLayout>

    <ImageView
        android:id="@+id/ivSecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_second"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Also make sure to add the gradle dependency at module level:

implementation 'com.google.android.flexbox:flexbox:3.0.0'

Preview:

enter image description here

Upvotes: 2

Ben P.
Ben P.

Reputation: 54264

You can achieve this by fixing ivSecond to the end of the parent and then creating a horizontal chain of tvTitle and ivFirst, so long as you apply a packed chain style and a bias of 0 to the chain and use constrainedWidth on the text view.

<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="wrap_content">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/ivFirst"
        app:layout_constraintHorizontal_bias="0"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="hello world"/>

    <ImageView
        android:id="@+id/ivFirst"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/ivSecond"
        app:layout_constraintStart_toEndOf="@id/tvTitle"
        app:layout_constraintTop_toTopOf="parent"/>

    <ImageView
        android:id="@+id/ivSecond"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

When the text is short, the first image is right up against it:

enter image description here

When the text is long, the first image stops at the edge of the second image and the text wraps to another line:

enter image description here

Upvotes: 6

SpiritCrusher
SpiritCrusher

Reputation: 21073

you can do it with layout_constrainedWidth . For this your text view needs to be constrained horizontally . try the layout below i have made few changes in it .

<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="wrap_content"
tools:ignore="MissingPrefix">

<TextView
    android:id="@+id/tvTitle"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:textSize="14sp"
    app:layout_constrainedWidth="true"
    app:layout_constraintEnd_toStartOf="@+id/ivFirst"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0" />

<ImageView
    android:id="@+id/ivFirst"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginEnd="16dp"
    android:src="@mipmap/ic_launcher"
    app:layout_constraintEnd_toStartOf="@id/ivSecond"
    app:layout_constraintStart_toEndOf="@id/tvTitle"
    app:layout_constraintTop_toTopOf="parent"
     />

<ImageView
    android:id="@+id/ivSecond"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@mipmap/ic_launcher"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
     />
    </androidx.constraintlayout.widget.ConstraintLayout>

Upvotes: 4

Related Questions