wholerabbit
wholerabbit

Reputation: 11536

Constraint layout: Cannot separate elements and keep them all on screen

I have a simple constraint layout like this:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/main_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@id/rescan"
        />

    <android.support.v7.widget.AppCompatButton
        android:id="@+id/rescan"
        android:layout_width="wrap_content"
        android:text="@string/rescan_button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintBottom_toBottomOf="parent"
        />

</android.support.constraint.ConstraintLayout>

Despite the layout_constraintBottom_toTopOf="@id/rescan", the listview potentially extends halfway through the button.

enter image description here

To try and correct that, I added hardcoded dimensions (which I prefer not to do); to the listview:

android:layout_marginBottom="50sp"

And to the button:

android:layout_height="40sp"
android:textSize="20sp"
android:layout_margin="10sp"

However, I then got this (emulator pic, the design view also corresponds to this):

enter image description here

The button is halfway off the screen.

So I decided to remove the hardcoded dimensions and use a barrier. The developer page is ambiguous about how barrierDirection is supposed to work, but this "constraintlayout.com" example makes it clear the direction should be the side you want the barrier on in relation to the elements listed in referenced_ids. Based on that, here's what I have inside the constraint layout:

<ListView
    android:id="@+id/main_list"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toTopOf="@id/bottomBarrier"
    />

<android.support.constraint.Barrier
    android:id="@+id/bottomBarrier"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:barrierDirection="top"
    app:constraint_referenced_ids="@id/rescan"
    />

<android.support.v7.widget.AppCompatButton
    android:id="@+id/rescan"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/rescan_button"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    />     

But things are not really getting better...

enter image description here

It's impossible to tell, but here the barrier is at the very bottom. Which explains why the listview, with Bottom_toTopOf the barrier, also now extends all the way to the bottom.

However, that makes the whole barrier, who's direction is top and who's constrained id is the button, totally pointless. In no sense is it keeping the listview on one side and the button on the other. It's below both of them.

Even more berserk: If I change the direction to bottom and leave everything else as it, the barrier jumps to the very top, the listview jumps halfway off the screen upward, and the button stays in place.

I'm totally flummoxed. My two biggest questions are:

  1. Why, in the first picture, does the listview extend halfway through the button, when it is set bottom-to-top of the button?

  2. Why, in the last picture, is the barrier, with a direction of "top" and referencing the button id, below the button?

Upvotes: 1

Views: 334

Answers (1)

Pawel Laskowski
Pawel Laskowski

Reputation: 6316

1. Your ListView's height is set to wrap_content which means the view will compute its own size and constraints will not limit the dimension. ConstraintLayout-1.1.0 introduced new attributes that allow using wrap_content yet keep enforcing the constraints to limit the specified dimension. These attribues are:

app:layout_constrainedWidth="true"
app:layout_constrainedHeight="true"

2. As for the Barrier, there's an error in the way you're referencing the view's id:

app:constraint_referenced_ids="@id/rescan"

This should be changed to:

app:constraint_referenced_ids="rescan"

Upvotes: 1

Related Questions