Search code examples
androidscrollviewandroid-constraintlayout

How can I make a ScrollView fill the rest of its parent's remaining space?


I have two TextViews and a ScrollView nested in a ConstraintLayout. Inside the ScrollView there is a TableLayout. The ScrollView's left, right and bottom constraints are set to "parent". The top constraint is set to the TextView just before it. Here is the XML:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:textSize="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView2" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView6">

        <TableLayout
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_marginStart="32dp"
            android:layout_marginTop="32dp"
            android:layout_marginEnd="32dp"
            android:layout_marginBottom="32dp"
            android:gravity="center"
            android:stretchColumns="0,1,2,3,4">

            <TableRow
                android:layout_width="fill_parent"
                android:layout_weight="1">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:text="1" />
                    ... 4 more TextViews
            </TableRow>
            ... many more TableRows
        </TableLayout>
    </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

The problem is that the ScrollView's width does not match its constraints. Instead, when more rows are added such that the ScrollView is taller than the its parent's remaining height, it overlaps the TextView just before it. The two screenshots below illustrate the problem:

No overlap:

enter image description here

Overlap:

enter image description here

When I set the ScrollView height to "0dp" (match constraints) it renders literally as 0dp (The ScrollView shrinks and none of its contents are shown).

What should I change to make the ScrollView expand and fill the remaining height of its parent container?


Solution

  • I would suggest several points (I couldn't figure out which one is critical):

    1. You shouldn't use match_parent for child views of a ConstraintLayout. Instead, use '0dp'.

    Official training:

    Note: You cannot use match_parent for any view in a ConstraintLayout. Instead use "match constraints" (0dp).

    2. You should not use @+id/xxx but use @id/xxx to specify other views. The former is for creating a new id.

    1. Change ConstraintLayout's layout_height to match_parent.

    2. Change TableLayout's layout_height to wrap_content.

    My result:

    screenshot

    layout.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout 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">
    
        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="bottom">
    
            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="TextView"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
    
            <TextView
                android:id="@+id/textView6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="TextView"
                android:textSize="16dp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/textView2" />
    
            <ScrollView
                android:layout_width="0dp"
                android:layout_height="0dp"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/textView6">
    
                <TableLayout
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="32dp"
                    android:layout_marginTop="32dp"
                    android:layout_marginEnd="32dp"
                    android:layout_marginBottom="32dp"
                    android:gravity="center"
                    android:stretchColumns="0,1,2,3,4">
    
                    <TableRow
                        android:layout_width="fill_parent"
                        android:layout_weight="1">
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="1" />
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="2" />
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="3" />
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="4" />
    
                        <TextView
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:text="5" />
                    </TableRow>
    
                   <!-- plenty of TableRows... -->
    
                </TableLayout>
            </ScrollView>
        </androidx.constraintlayout.widget.ConstraintLayout>
    </FrameLayout>