求助:多个ExpandableListView在ScrollView中展开时无法撑开高度
问题解决:ScrollView嵌套ExpandableListView展开后高度挤压
核心问题在于ScrollView与ExpandableListView的滚动特性冲突,原生ExpandableListView的wrap_content无法自动计算展开后的总高度,再加上原布局中ConstraintLayout的错误约束(所有列表都绑定了bottom_toBottomOf="parent"),导致展开的子项被挤压在初始高度范围内。
以下是分步解决方案:
1. 重构布局结构
原ConstraintLayout的约束设置会让所有ExpandableListView重叠布局,完全错误。换成垂直LinearLayout实现列表依次排列:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".screens.home.ui.dailyreportes.DailyReportsDetailsFragment"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!-- 替换为自定义的ExpandableHeightListView --> <com.your.package.ExpandableHeightListView android:id="@+id/elv_work_logs" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@android:color/darker_gray" android:dividerHeight="0.5dp" /> <com.your.package.ExpandableHeightListView android:id="@+id/elv_equipment_logs" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@android:color/darker_gray" android:dividerHeight="0.5dp" /> <com.your.package.ExpandableHeightListView android:id="@+id/elv_material_delivery_logs" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@android:color/darker_gray" android:dividerHeight="0.5dp" /> <com.your.package.ExpandableHeightListView android:id="@+id/elv_activity_logs" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@android:color/darker_gray" android:dividerHeight="0.5dp" /> <com.your.package.ExpandableHeightListView android:id="@+id/elv_schedule_delays_logs" android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@android:color/darker_gray" android:dividerHeight="0.5dp" /> </LinearLayout> </ScrollView> </LinearLayout>
2. 自定义ExpandableListView实现高度自适应
原生ExpandableListView不会在组展开/折叠时重新计算总高度,我们需要重写onMeasure方法,手动计算所有可见项(包括展开的子项)的总高度:
public class ExpandableHeightListView extends ExpandableListView { public ExpandableHeightListView(Context context) { super(context); } public ExpandableHeightListView(Context context, AttributeSet attrs) { super(context, attrs); } public ExpandableHeightListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int totalHeight = 0; // 遍历所有组项 for (int i = 0; i < getCount(); i++) { View groupView = getChildAt(i); if (groupView != null) { // 测量组项高度 groupView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); totalHeight += groupView.getMeasuredHeight(); // 如果当前组是展开状态,测量所有子项高度 if (isGroupExpanded(i)) { int childCount = getExpandableListAdapter().getChildrenCount(i); for (int j = 0; j < childCount; j++) { View childView = getExpandableListAdapter().getChildView(i, j, false, null, this); childView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); totalHeight += childView.getMeasuredHeight(); } } } } // 加上分隔线总高度 totalHeight += getDividerHeight() * (getCount() - 1); // 重新设置测量高度 heightMeasureSpec = MeasureSpec.makeMeasureSpec(totalHeight, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
注意将com.your.package替换为你自己的项目包名。
3. 代码中添加展开/折叠监听
给每个ExpandableListView设置适配器后,添加组展开/折叠监听,触发布局重新测量:
// 示例:给工作日志列表设置监听 ExpandableHeightListView workLogsListView = findViewById(R.id.elv_work_logs); workLogsListView.setAdapter(yourWorkLogsAdapter); workLogsListView.setOnGroupExpandListener(groupPosition -> { workLogsListView.requestLayout(); // 展开时重新计算高度 }); workLogsListView.setOnGroupCollapseListener(groupPosition -> { workLogsListView.requestLayout(); // 折叠时重新计算高度 });
其他四个列表重复上述监听设置即可。
关键说明
ScrollView添加android:fillViewport="true"是为了让内部布局在内容不足时填满屏幕,内容超出时正常滚动。- 原布局中
android:layout_weight属性在ConstraintLayout中无效,已直接移除,避免布局混乱。
内容的提问来源于stack exchange,提问作者Ahmed Laoun
相关产品推荐
相关产品推荐

