17.Android ScrollView嵌套ListView 技巧
需求所致
现在的需求中,一个简单的列表已经不能满足产品的设计。往往都是在一个View中会有许多控件,ListView又包含在其中。我们都知道,这样的页面肯定是一个屏幕的长度都不能符合的,然而ListView又是滚动的,这次就出现了ScrollView嵌套ListView的尴尬场面。但是!ScrollView又只能有一个子控件,又只能用外面包装一个无用的Layout去对接。
巧妙避免
其实很多时候的需求往往是,一个列表,然后上面有一堆View。这次可以不用ScrollView嵌套ListView的处理。直接把上面拿一堆View包裹起来,作为ListView的HeadView添加进去。 同理,FootView也是一样,但是过于复杂的页面,可以考虑ScrollView嵌套ListView的处理。
解决方案一 手动设置ListView高度
解决思路: 手动设定ListView的高度,在ListView设置了Adapter之后使用。
注意: Adapter中getView方法返回的View的布局只能是LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局,在调用listItem.measure(0, 0);时就会抛异常,除LinearLayout外的其他布局的这个方法就是直接抛异常的。
/**
* 动态改变ListView的高度
* @param listView
*/
public static void setListViewHeightBasedOnChildren(ListView listView) {
if(listView == null) return;
ListAdapter adapter = listView.getAdapter();
if (adapter == null) {
return;
}
int totalHeight = 0;
// 开始计算ListView里所有Item加起来的总高度
for (int i = 0; i < adapter.getCount(); i++) {
View listItem = adapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
// 高度 = 所有分割线高度 + Item总高度
params.height = totalHeight + (listView.getDividerHeight() * (adapter.getCount() - 1));
listView.setLayoutParams(params);
}
解决方案二 一个ListView渲染整个ScrollView内容
解决思路: 把ScrollView内的所用内容,全部都放到ListView中去渲染,ListView上、下方的View都作为ListView的Item去渲染,ListView中的普通Item是平级关系。
注意: 这里涉及到一个打破ViewHolder复用问题。我们可以看getView源代码,convertView返回的是旧视图(可以看看Android 万能ViewHolder,这里详解了convertView来源)。那么问题来了ÿ