Wrap right-aligned view when there is no space

2.5k Views Asked by At

I have 2 views in a layout - TextView and Button. TextView is aligned/anchored to the left side and the button is to the right side.

What I'm trying to achieve is the natural "wrap behavior" of the Button. When TextView will be wide enough so that there won't be space for the button (in the same line), it should move below the TextView, while still anchored to the right.

Here are 3 scenarios for the layout which I want to achieve:

mockup


I was trying to make this with FlexBoxLayout, but the button appears on the left side after wrapping.

<com.google.android.flexbox.FlexboxLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:flexDirection="row"
    app:flexWrap="wrap"
    app:justifyContent="space_between"
   >


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="text text"
        android:gravity="start"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:text="Button"
        />

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

So how can I do that? It doesn't need to be FlexBox, I can use any layout, even 3rd party.

3

There are 3 best solutions below

0
On

No need for a 3rd party layout. ConstraintLayout should be more than enough - with a small tweak in code.

Your TextView will have straightforward constraints, set to parent layout (start, top, end).

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="48dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Text text text text text text" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/text" />
</android.support.constraint.ConstraintLayout>

In the code, just check the width of the TextView and compare it with the width of the parent (basically check it should overlap with the button).

If it does change(you will have to do this in code but this is the principle):

app:layout_constraintTop_toTopOf="@+id/text"

to

app:layout_constraintTop_toBottomOf="@+id/text"

If you need to do this dynamically ConstraintLayout has neat feature "Keyframe animations" that creates awesome looking animations when you are changing constraints.

0
On

Doesn't seem like there is a way to do it with Flexbox. I would just do it programmatically when you've inflated the resource (in onCreateView() or something like that). The parent of both of the views would be a RelativeLayout, with the Button aligned to the TextView top when the widths combined don't exceed the width of the RelativeLayout, and aligned to the bottom of the TextView when the widths are larger than that.

0
On

Use justifyContent="flex_end" in the parent and set layout_flexGrow to the children like this works for me.

<com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="300dp"
    android:layout_height="wrap_content"
    app:flexDirection="row"
    app:flexWrap="wrap"
    app:justifyContent="flex_end">

    <TextView
        android:id="@+id/textview2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="blah blah"
        app:layout_flexGrow="1" />

    <TextView
        android:id="@+id/textview3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="( . )( . )"
        app:layout_flexGrow="0" />
</com.google.android.flexbox.FlexboxLayout>