idunnololz
idunnololz

Reputation: 8363

How to layout a row of buttons with ConstraintLayout

I'm currently trying to layout something that I originally thought should be pretty easy with ConstraintLayout but after attempting it, I've realized I have no idea how to achieve this.

The idea is simple, layout a dialog-like view using a ConstraintLayout with no nesting.

enter image description here

The xml for this is simple (see below). The issue arrises when I wanted to make this layout scale for longer text on the buttons. For instance the desired layout might look like:

enter image description here

I was ultimately unable to come up with a nice solution that can work with:

Here's my layout xml if anyone wants to play with it.


<?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="wrap_content"
    android:padding="16dp">

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:paddingTop="24dp"
        tools:text="Some title"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <TextView
        android:id="@+id/body"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:paddingTop="8dp"
        tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam luctus neque quis nunc ornare varius."
        app:layout_constraintTop_toBottomOf="@+id/title"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>

    <Button
        android:id="@+id/negativeButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginStart="16dp"
        style="@style/Widget.AppCompat.Button.Borderless"
        tools:text="Cancel"
        app:layout_constrainedWidth="true"
        app:layout_constraintHorizontal_bias="1"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/positiveButton"
        app:layout_constraintTop_toBottomOf="@+id/body"/>

    <Button
        android:id="@+id/positiveButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        style="@style/Widget.AppCompat.Button.Borderless.Colored"
        tools:text="Ok"
        app:layout_constrainedWidth="true"
        app:layout_constraintStart_toEndOf="@+id/negativeButton"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/negativeButton"
        app:layout_constraintBottom_toBottomOf="@+id/negativeButton"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Edit: Just to list some things I've tried (and failed):

Edit2: Just to add more info. I am trying to make this as generic as possible since I wanted to create a re-usable component. So it should just work with button text of any length and not just specific text. This is a good idea anyways since localization can often cause the button text to be longer or shorter.

Upvotes: 1

Views: 1885

Answers (3)

Ben P.
Ben P.

Reputation: 54204

I do not believe this is possible with ConstraintLayout. There is no mechanism that will let you have both buttons behave "intelligently" when they both grow too large.

That said, here's something you could do to get close. First, set up a packed horizontal chain with a bias of 1:

app:layout_constraintHorizontal_bias="1"
app:layout_constraintHorizontal_chainStyle="packed"

Then use these two attributes to control the width of both of your buttons:

android:layout_width="0dp"
app:layout_constraintWidth_default="wrap"

This will give what you asked for, but only as long as the second button does not grow wide enough to fill the screen (at which point it will consume all of the available space).

enter image description here

enter image description here

enter image description here

To work around that, you can either set a minimum width on the first button:

app:layout_constraintWidth_min="100dp"

enter image description here

Or set a maximum width on the second button:

app:layout_constraintWidth_max="200dp"

enter image description here

Upvotes: 1

Jarvis
Jarvis

Reputation: 402

You can use guidelines to aid in laying out buttons. You'll want to constrain the rightmost button to the right guideline and have that guideline set at about 0.90 and have the left button's constraint_start to startOf parent. Constrain the right of the left button to the start of the right button.

Adjust the margins on the guidelines to account for additional padding requirements.

<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="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:padding="10dp">
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline_left_vertical"
        android:layout_width="2dp"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.05" />
    <Button android:id="@+id/leftButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        app:layout_constraintEnd_toStartOf="@+id/rightButton"
        app:layout_constraintStart_toEndOf="@id/guideline_left_vertical"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Some Teggggggfffffffffffeeeeext" />
    <Button android:id="@+id/rightButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginStart="2dp"
        tools:text="Helfffghhhhhhhhhhlo"
        app:layout_constraintEnd_toStartOf="@+id/guideline_right_vertical"
        app:layout_constraintStart_toEndOf="@+id/leftButton"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline_right_vertical"
        android:layout_width="2dp"
        android:layout_marginStart="5dp"
        android:layout_height="2dp"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.95" />

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

Upvotes: 0

Chooven
Chooven

Reputation: 105

easiest way is to add android:maxWidth="200dp" to the button you want to restrict

Upvotes: 0

Related Questions