Align views right in ConstraintLayout without clipping

VIN picture VIN · Apr 11, 2018 · Viewed 23.6k times · Source

I am creating a dialog with two buttons aligned right in relation to the parent ConstraintLayout.

Everything is fine, until the text of the buttons becomes very long. When the text of either or both buttons is lengthy, the buttons extend beyond the bounds of the parent, causing clipping of the text, as shown in the image below. I would like to handle cases where there is longer text.

i.e. The desired behavior would be

  • buttons should wrap text when text is long
  • buttons should stay within bounds of parent and obey parent padding
  • buttons should stay aligned right of parent

When button text is short, the layout works as intended:

enter image description here

When button text is long:

  • Cancel text is truncated when cancel button text is long. This is happening because the button itself is being pushed past the parent's boundaries. enter image description here
  • Cancel text pushed beyond parent boundaries when ok button's text is long, again, because the button is pushed beyond the parent's boundaries. enter image description here

Layout code

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="@dimen/dialog_padding"
    android:paddingLeft="@dimen/dialog_padding"
    android:paddingRight="@dimen/dialog_padding"
    android:paddingTop="@dimen/dialog_padding">

    <TextView
        android:id="@+id/dialog_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dialog_text_margin"
        tools:text="Dialog title" />

    <TextView
        android:id="@+id/dialog_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dialog_text_margin"
        app:layout_constraintTop_toBottomOf="@id/dialog_title"
        tools:text="Dialog text content" />

    <Button
        android:id="@+id/cancel_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toStartOf="@id/ok_btn"
        app:layout_constraintTop_toBottomOf="@id/dialog_content"
        tools:text="Dismiss" />

    <Button
        android:id="@+id/ok_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/dialog_content"
        tools:text="Accept" />
</android.support.constraint.ConstraintLayout>

Things that I've tried to no avail:

  • adding app:layout_constraintStart_toStartOf="parent" to the cancel button causes the buttons to no longer be aligned right, and so that solution is incorrect
  • constraining the end of the dismiss button to the start of the accept button causes buttons to no longer be aligned right
  • using layout_width="0dp" for the buttons and using app:layout_constrainedWidth="true" has no effect

Answer

Cheticamp picture Cheticamp · Apr 12, 2018

Here are two screen shots of what I think you are trying to accomplish.

First, with some short text:

enter image description here

Now with some long text:

enter image description here

I took a few liberties with the layout and introduced a guideline at 33% of the width that the button are constrained to. You didn't specify how much the button could expand horizontally, so I made this assumption.

The XML for this layout follows. I set the width of the buttons to 0dp or match_constraints so their size would adjust. The buttons have also been placed into a packed chain that groups the two buttons together. The horizontal bias is set to 0.5 now, but increasing it will move the group to the right if it starts to creep left on you.

The ConstraintLayout documentation has some good descriptions of these features and how to use them.

<android.support.constraint.Guideline
    android:id="@+id/guideline"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.33" />

<TextView
    android:id="@+id/dialog_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/dialog_text_margin"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="Dialog title" />

<Button
    android:id="@+id/cancel_btn"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toStartOf="@+id/ok_btn"
    app:layout_constraintHorizontal_chainStyle="packed"
    app:layout_constraintStart_toEndOf="@+id/guideline"
    app:layout_constraintTop_toBottomOf="@+id/dialog_title"
    tools:text="Dismiss" />

<Button
    android:id="@+id/ok_btn"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginEnd="8dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toEndOf="@+id/cancel_btn"
    app:layout_constraintTop_toTopOf="@+id/cancel_btn"
    tools:text="Accept" />