ScrollView嵌套两个ExpandableListView初始仅显示一个的问题求助
解决ScrollView嵌套多个ExpandableListView初始仅显示一个的问题
这个问题的核心原因是:ScrollView中的ExpandableListView使用wrap_content时,默认只会测量并显示组标题的高度,子项高度不会被计算进去。初始状态下第一个ExpandableListView的高度只有组标题那么高,第二个ListView被挤到了可视区域之外,只有当第一个展开后高度增加,第二个才会被推到可见位置。
下面是具体的解决步骤和代码修改方案:
1. 初始化时主动计算两个ListView的完整高度
你当前的setListViewHeight方法只在点击组的时候调用,初始状态下没有执行高度计算。我们需要在设置完适配器后,立刻为两个ExpandableListView计算并设置完整高度。
修改你的onCreateView方法,添加初始化时的高度计算:
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View convertView = inflater.inflate(R.layout.cafes_more_fragment, container, false); // 初始化第一个ExpandableListView final ExpandListChild1 items = new ExpandListChild1(); exLInTheMoodFor = (ExpandableListView) convertView.findViewById(R.id.exLInTheMoodFor); ExpListItems = SetStandardGroups(); ExpAdapter = new ExpandListAdapterProduct(activity, ExpListItems); exLInTheMoodFor.setAdapter(ExpAdapter); // 初始化时就计算高度 setListViewHeight(exLInTheMoodFor); // 初始化第二个ExpandableListView(假设你的第二个ListView id是exLAnother) ExpandListChild2 anotherItems = new ExpandListChild2(); exLAnother = (ExpandableListView) convertView.findViewById(R.id.exLAnother); AnotherExpListItems = SetAnotherGroups(); AnotherExpAdapter = new ExpandListAdapterProduct(activity, AnotherExpListItems); exLAnother.setAdapter(AnotherExpAdapter); // 同样初始化计算高度 setListViewHeight(exLAnother); // 保留原有的点击事件逻辑(如果需要点击展开/折叠时调整高度) exLInTheMoodFor.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) { setListViewHeight(exLInTheMoodFor); return false; } }); // 第二个ListView的点击事件同理 exLAnother.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView expandableListView, View view, int i, long l) { setListViewHeight(exLAnother); return false; } }); return convertView; }
2. 修改高度计算方法,计算所有组和子项的总高度
原来的setListViewHeight方法逻辑是根据点击的组来判断是否包含子项高度,我们需要修改它,让它默认计算所有组(包括子项)的完整高度,不管当前组是否展开:
// 调整后的高度计算方法,移除group参数 private void setListViewHeight(ExpandableListView listView) { ExpandableListAdapter listAdapter = listView.getExpandableListAdapter(); if (listAdapter == null) { // 适配器为空时直接返回 return; } int totalHeight = 0; int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.EXACTLY); // 遍历所有组,计算组标题高度 for (int i = 0; i < listAdapter.getGroupCount(); i++) { View groupItem = listAdapter.getGroupView(i, false, null, listView); groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); totalHeight += groupItem.getMeasuredHeight(); // 遍历当前组的所有子项,计算子项高度 for (int j = 0; j < listAdapter.getChildrenCount(i); j++) { View listItem = listAdapter.getChildView(i, j, false, null, listView); listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); totalHeight += listItem.getMeasuredHeight(); } } // 添加分割线的总高度 totalHeight += listView.getDividerHeight() * (listAdapter.getGroupCount() - 1); // 设置ListView的高度,兜底最小高度避免显示异常 ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight > 0 ? totalHeight : 200; listView.setLayoutParams(params); listView.requestLayout(); }
关键注意事项
- 确保两个ExpandableListView的
android:layout_height都设置为wrap_content,这样我们动态设置的LayoutParams才能生效。 - 如果你的列表数据是异步加载的(比如从网络获取),要在数据加载完成后再调用
setListViewHeight方法,否则会因为适配器为空或数据不全导致高度计算错误。 - 额外提醒:这种ScrollView嵌套ExpandableListView的方式会导致所有列表项被一次性测量和绘制,没有复用机制,当列表数据量大时会影响性能。如果可能的话,建议改用单一ExpandableListView(把两个列表的组合并),或者用RecyclerView实现类似的展开/折叠效果,性能会更优。
内容的提问来源于stack exchange,提问作者Sarthak Sharma
相关产品推荐
相关产品推荐

