7

I have an issue using a ScrollView inside ConstraintLayout (constraint-layout:1.0.0-beta3)

The content of my ScrollView isn't showed entirely.

Here is my layout:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_test"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:background="#212121">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Constraint Layout"
            android:textSize="45sp"/>

    </LinearLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/header"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="BUTTON"
                android:layout_marginTop="800dp"/>


        </LinearLayout>

    </ScrollView>

</android.support.constraint.ConstraintLayout>

And here is the result

enter image description here

As you can see the button isn't visible and I reached the bottom of my ScrollView.

It seems to works well with LinearLayout with layout below

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_test"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="#212121">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Linear Layout"
            android:textSize="45sp"/>

    </LinearLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <Button
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="BUTTON"
                android:layout_marginTop="800dp"/>


        </LinearLayout>

    </ScrollView>

</LinearLayout>

And result is

enter image description here

With LinearLayout end of ScrollView is reachable.

Is there a bug with ConstraintLayout or do I made something wrong?

2
  • 1
    That android:layout_marginTop="800dp" on the button looks a little sketchy... Did you want the button to always show at the bottom of the screen and have the ScrollView sit on top of that? Commented Nov 16, 2016 at 16:45
  • This marginTop is an example to force the Button to be visible only after scrolling to bottom of ScrollView. I wanted to illustrate the behavior with a tiny example. Commented Nov 16, 2016 at 16:49

2 Answers 2

11

The way I would have done it is:

<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_test"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/header"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#212121"
        android:text="Constraint Layout"
        android:textSize="45sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ScrollView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:fillViewport="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/header">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <Button
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:text="BUTTON"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent" />

        </android.support.constraint.ConstraintLayout>

    </ScrollView>

</android.support.constraint.ConstraintLayout>

Which gives:

enter image description here

A few things to keep in mind:

  • you don't need a linearlayout for the header, you can just use the textview directly.
  • don't use match_parent, it might seem to work, but is undefined. Use 0dp instead with the correct constraints to stretch the view as you want.
  • clearly, don't use a 800dp margin. It might look ok on your particular screen, but won't give you what you want on different devices.
  • scrollview by default will wrap its content -- the fillViewport attribute is here to make it takes the indicated space
  • you can use nested ConstraintLayout when it makes sense. In the future, we might also take advantage of it to do some performance improvements
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for precisions :)
-1

I changed the height of the ScrollView to match_parent and added a bottom constraint. This seemed to make it work correctly.

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/header"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

Note: Having a height of wrap_content on a vertically scrolling view usually doesn't end well, in any layout.

5 Comments

Indeed, my issue was coming from there. Thank you!
actually -- match_parent is NOT supported in ConstraintLayout, so it won't do what you think it does. It might seem to work in your example, but it likely will be broken on other devices. You can replicate the match_parent behavior though, but you have to explicitly define the constraints. See stackoverflow.com/questions/40633299/…
@NicolasRoard I had to do both things -- set the height to match_parent and add the bottom constraint -- to make the layout correct. Doing either one or the other was not sufficient.
@krislarson see my answer -- match_parent is undefined with ConstraintLayout.
You can use 0dp instead of match_parent for layout_height and it works well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.