问题
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