3

I have a form as a ConstraintLayout, like this:

enter image description here

"Full Name" and "Password" are aligned on their right edge, and "Full Name" is providing the margin from the ConstraintLayout:

enter image description here

So far all is fine, but I wonder about how to properly handle the case where I need to change those texts programmatically. If "Full Name" gets bigger or smaller, "Password" will remain aligned:

Full name gets bigger and it's still on screen

BUT if "Password" changes its size, it will get out of screen:

Password gets bigger and gets out of screen

I tried to use a Barrier to get the left edge of both "Full Name" and "Password", but I couldn't get it to work, I think a Barrier can only relate to other elements and not to align the elements of the barrier to the edges (correct me if I am wrong, please).

This case is particularly important for me to avoid making several different layouts for languages where the translation of "Full Name" and "Password" could change their sizes and make the text get out of screen.

So, how can I avoid "Full Name" and "Password" getting out of screen, if their text changes, and also have the EditTexts expand to their right edge, as in the picture?

pfx
  • 20,323
  • 43
  • 37
  • 57
Michel Feinstein
  • 13,416
  • 16
  • 91
  • 173
  • Have a look [here](https://stackoverflow.com/questions/49216128/constraintlayout-treats-multiple-horizontal-chains-differently) for an example using a barrier. You would set the barrier to be to the right of the largest label, then line up the EditTexts with the barrier. – Tyler V Sep 06 '18 at 00:31
  • This example covers the right edge... My problem is the left edge – Michel Feinstein Sep 06 '18 at 00:32
  • It should still be possible. I'll try to put together an example. – Tyler V Sep 06 '18 at 00:33
  • Looks like @Cheticamp beat me to it. That answer is a good solution. – Tyler V Sep 06 '18 at 03:24
  • It works, but it's only possible on code, Android Studio blocks circular references – Michel Feinstein Sep 06 '18 at 03:28

2 Answers2

4

This is an interesting test for ConstraintLayout. The following layout works under versions 1.1.2 and 1.1.3 but not tested in other releases.

The key is to constrain the ends of the full name and password fields to each other and their starts to the start of the parent. Set the horizontal bias to 1.0 to make the two fields right-align.

I was wondering if the circular reference (end <-> end) would resolve happily and it does. I now wonder if this solution just happens to work but may break in a future release.

enter image description here

enter image description here

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/fullName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="50dp"
        android:text="Full Name"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintEnd_toEndOf="@+id/password"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="24dp"
        android:text="Password is longer"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintEnd_toEndOf="@id/fullName"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/fullName" />

    <View
        android:id="@+id/view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:background="@android:color/holo_blue_light"
        app:layout_constraintBottom_toBottomOf="@id/fullName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/fullName"
        app:layout_constraintTop_toTopOf="@id/fullName" />

    <View
        android:id="@+id/view2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:background="@android:color/holo_blue_light"
        app:layout_constraintBottom_toBottomOf="@id/password"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/password"
        app:layout_constraintTop_toTopOf="@id/password" />

</androidx.constraintlayout.widget.ConstraintLayout>

Here is a second take that also uses a circular reference. A barrier is placed to the right of the text fields and those same fields have their ends tied to the barrier. A horizontal bias of 1.0 right justifies the text. The screen snapshots look the same as above, so I will not reproduce them here.

I think that this method is preferable and, IMHO, less likely to break.

activity_main2.xml

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/fullName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="50dp"
        android:text="Full Name"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintEnd_toEndOf="@+id/barrier"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/password"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="24dp"
        android:text="Password is longer"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintEnd_toStartOf="@id/barrier"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/fullName" />

    <View
        android:id="@+id/view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:background="@android:color/holo_blue_light"
        app:layout_constraintBottom_toBottomOf="@id/fullName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/barrier"
        app:layout_constraintTop_toTopOf="@id/fullName" />

    <View
        android:id="@+id/view2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:background="@android:color/holo_blue_light"
        app:layout_constraintBottom_toBottomOf="@id/password"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/barrier"
        app:layout_constraintTop_toTopOf="@id/password" />

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="right"
        app:constraint_referenced_ids="fullName,password" />

</androidx.constraintlayout.widget.ConstraintLayout>
Cheticamp
  • 61,413
  • 10
  • 78
  • 131
1

TableLayout is better then ConstraintLayout in your case, the layout could be like this:

<TableLayout android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="24dp"
    android:stretchColumns="1">
    <TableRow>
        <TextView android:gravity="end"
            android:text="Full Name"/>
        <EditText/>
    </TableRow>
    <TableRow>
        <TextView android:gravity="end"
            android:text="Password"/>
        <EditText/>
    </TableRow>
</TableLayout>

When you change one of the two TextView, they will be automatically aligned again.

Run
  • 2,148
  • 2
  • 12
  • 29