ScrollView嵌套RelativeLayout/ConstraintLayout时底部视图显示不全
ScrollView小屏底部内容截断问题修复
现象
实现纵向滚动布局时,大屏设备展示完全正常,小屏设备滚动到底部时最后一个视图无法完整显示,分别使用RelativeLayout、ConstraintLayout作为ScrollView直接子布局时异常表现一致。
- 预期效果:


- 异常表现:

问题根源
问题出在两个布局实现里,都给最后一个TextView同时设置了「排列在上一个控件下方」和「对齐父布局底部」的属性,和ScrollView的android:fillViewport="true"属性产生了测量冲突:
- RelativeLayout版本中,最后一个TextView同时配置了
android:layout_below="@id/box3"和android:layout_alignParentBottom="true" - ConstraintLayout版本中,最后一个TextView同时配置了
app:layout_constraintTop_toBottomOf="@+id/box3"和app:layout_constraintBottom_toBottomOf="parent"
开启fillViewport属性后,ScrollView会强制将直接子布局的最小高度拉到和屏幕可视区域高度相等。当小屏设备上内容总高度超过屏幕高度时,这组冲突的约束会让系统计算滚动总高度时漏算最后一个View的高度和对应的边距,滚动区域高度比实际内容高度小,自然无法滚动到最底部,最后一个控件就被截断。而大屏设备上内容总高度本来就小于屏幕高度,不会触发滚动,所以看起来展示正常。
修复方案
如果不需要实现「内容不足一屏时最后一个控件贴屏幕底部」的效果,直接删掉最后一个TextView的「对齐父布局底部」属性即可:
- RelativeLayout版本删除
android:layout_alignParentBottom="true" - ConstraintLayout版本删除
app:layout_constraintBottom_toBottomOf="parent"
如果需要兼顾「短内容贴底、长内容可滚动」的效果,调整ConstraintLayout版本的写法即可,参考代码:
<?xml version="1.0" encoding="utf-8"?> <ScrollView 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" android:background="#959494" android:fillViewport="true" android:scrollbars="none"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="@dimen/_12sdp"> <com.google.android.material.card.MaterialCardView android:id="@+id/box1" android:layout_width="160dp" android:layout_height="160dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="packed"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="Box 1" android:textColor="#000" android:textSize="30sp" /> </com.google.android.material.card.MaterialCardView> <com.google.android.material.card.MaterialCardView android:id="@+id/box2" android:layout_width="160dp" android:layout_height="160dp" android:layout_marginTop="12dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/box1"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="Box 2" android:textColor="#000" android:textSize="30sp" /> </com.google.android.material.card.MaterialCardView> <com.google.android.material.card.MaterialCardView android:id="@+id/box3" android:layout_width="160dp" android:layout_height="160dp" android:layout_marginTop="12dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/box2" app:layout_constraintBottom_toTopOf="@+id/textView1"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="Box 3" android:textColor="#000" android:textSize="30sp" /> </com.google.android.material.card.MaterialCardView> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/_12sdp" android:textColor="#fff" android:textSize="30sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/box3" tools:text="This is a Textview" /> </androidx.constraintlayout.widget.ConstraintLayout> </ScrollView>
内容的提问来源于stack exchange,提问作者ShaRy
相关产品推荐
相关产品推荐

