How can I use ConstraintLayout to have the first View shrink to fit remaining space?

删除回忆录丶 提交于 2019-12-10 09:27:04

问题


I have the following layout. Notice Z is positioned below Y, but constrained to the bottom. There is a nice gap gap between Y and Z, afforded by the excess vertical space. This is my desired and actual behavior when there is excess vertical space.

However, I run out of excess vertical space when the keyboard is shown.

Desired Behavior (no excess vertical space) When I run out of vertical space, I would like the following to occur: X (ScrollView), shrinks to fill the remaining space, allowing Y and Z to be displayed at full size.

Actual Behavior (no excess vertical space) Y shrinks instead.

My source is below. How can I modify it to get my desired behavior in both scenarios (excess vertical space and no excess vertical space)?

<androidx.constraintlayout.widget.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">

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#fbe9e7"
            android:gravity="center"
            android:text="X"
            android:textSize="96sp">

        </TextView>
    </ScrollView>

    <TextView
        android:id="@+id/text_Y"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f3e5f5"
        android:gravity="center"
        android:text="Y"
        android:textSize="96sp"
        app:layout_constraintTop_toBottomOf="@+id/scrollView" />

    <TextView
        android:id="@+id/text_Z"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#e1f5fe"
        android:gravity="center"
        android:text="Z"
        android:textSize="96sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_Y"
        app:layout_constraintVertical_bias="1" />

</androidx.constraintlayout.widget.ConstraintLayout>

The issue largely stems from the X scrollview needing to be 0dp when vertical space is limited, but wrap_content when there is excess vertical space

Note: you can demo how the layout will behave with less vertical space by dragging the bottom right corner accordingly in the preview pane for a layout in Android Studio


回答1:


try this

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@+id/text_Y"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0"
        app:layout_constraintVertical_chainStyle="packed">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#fbe9e7"
            android:gravity="center"
            android:text="X"
            android:textSize="96sp">

        </TextView>
    </ScrollView>

    <TextView
        android:id="@+id/text_Y"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f3e5f5"
        android:gravity="center"
        android:text="Y"
        android:textSize="96sp"
        app:layout_constraintBottom_toTopOf="@+id/text_Z"
        app:layout_constraintTop_toBottomOf="@+id/scrollView"
        app:layout_constraintVertical_bias="0" />

    <TextView
        android:id="@+id/text_Z"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#e1f5fe"
        android:gravity="center"
        android:text="Z"
        android:textSize="96sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>



回答2:


I would recommend a barrier constraint: https://developer.android.com/reference/android/support/constraint/Barrier

You would have the barrier be the top of the two bottom views, Z and the an empty view that goes from the parent bottom to the bottom of Y.

<androidx.constraintlayout.widget.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">

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#fbe9e7"
        android:gravity="center"
        android:text="X"
        android:textSize="96sp">

    </TextView>
</ScrollView>

<TextView
    android:id="@+id/text_Y"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#f3e5f5"
    android:gravity="center"
    android:text="Y"
    android:textSize="96sp"
    app:layout_constraintTop_toBottomOf="@+id/scrollView" 
    app:layout_constraintBottom_topTopOf="@+barrier_bottom"/>

<androidx.constraintlayout.widget.Barrier
            android:id="@+id/barrier_bottom"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:barrierDirection="bottom"
            app:constraint_referenced_ids="text_Z,spacer" />

<TextView
    android:id="@+id/spacer
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_constraintTop_topBottomOf="@+id/text_Y"
    app:layout_constraintBottom_toBottomOf="parent"/>

<TextView
    android:id="@+id/text_Z"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#e1f5fe"
    android:gravity="center"
    android:text="Z"
    android:textSize="96sp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintVertical_bias="1" />

</androidx.constraintlayout.widget.ConstraintLayout>



回答3:


As far as I tested my own solution, I found that your desired behaviour is not achievable. I've spent approximately 2 hours combining different variations of chains and another ConstraintLayout stuff. This is the only possible solution I've got. TextY and TextZ after resizing stay fully visible, but TextX doesn't resize staying the same height and hiding behind TextY.

Solution itself:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#fbe9e7"
            android:gravity="center"
            android:text="X"
            android:textSize="96sp">

        </TextView>
    </ScrollView>

    <TextView
        android:id="@+id/text_Y"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f3e5f5"
        android:gravity="center"
        android:text="Y"
        android:textSize="96sp"
        app:layout_constraintBottom_toTopOf="@id/text_Z"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/scrollView"
        app:layout_constraintVertical_bias="1"
        app:layout_constraintVertical_chainStyle="spread_inside" />

    <TextView
        android:id="@+id/text_Z"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#e1f5fe"
        android:gravity="center"
        android:text="Z"
        android:textSize="96sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text_Y" />

</androidx.constraintlayout.widget.ConstraintLayout>




回答4:


The below code works as you would expect it to, have tested it personally. It is worth noting that the behavior you desire, i.e the scrollview changing its size when the text_y starts overlapping it, cannot be achieved with only a single constraint layout, so I've put the text_y and text_z in another constraint layout.

<androidx.constraintlayout.widget.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">

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintHeight_max="wrap"
        app:layout_constraintBottom_toTopOf="@id/constraint"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="spread_inside"
        app:layout_constraintVertical_bias="0">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#fbe9e7"
            android:gravity="center"
            android:text="X"
            android:textSize="96sp">

        </TextView>
    </ScrollView>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constraint"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintHeight_min="wrap"
        app:layout_constraintTop_toBottomOf="@id/scrollView"
        app:layout_constraintBottom_toBottomOf="parent">  
        <TextView
            android:id="@+id/text_Y"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#f3e5f5"
            android:gravity="center"
            android:text="Y"
            android:textSize="96sp"
            app:layout_constraintVertical_chainStyle="spread_inside"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toTopOf="@id/text_Z"/>

        <TextView
            android:id="@+id/text_Z"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#e1f5fe"
            android:gravity="center"
            android:text="Z"
            android:textSize="96sp"
            app:layout_constraintTop_toBottomOf="@id/text_Y"
            app:layout_constraintBottom_toBottomOf="parent"/>
    </androidx.constraintlayout.widget.ConstraintLayout>


</androidx.constraintlayout.widget.ConstraintLayout>


来源:https://stackoverflow.com/questions/58278029/how-can-i-use-constraintlayout-to-have-the-first-view-shrink-to-fit-remaining-sp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!