在很多页面中都有着Scrollview 嵌套ListView的界面。在工作中用到的这种情况也比较多。但随之而来的就是Scrollview 嵌套ListView显示不全的问题。
显示不全的时候,首先就会想到重新去计算listview的高度,不就行了。于是就有手动去设置listview的高度,
手动设置ListView高度
经过测试发现,在xml中直接指定ListView的高度,是可以解决这个问题的,但是ListView中的数据是可变的,实际高度还需要实际测量。
/**
* 动态设置ListView的高度
* @param listView
*/
public static void setListViewHeightBasedOnChildren(ListView listView) {
if(listView == null) return;
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
可是在我设置重新计算后,却怎么都没有变,然后这是所要注意的几点细节:
一是这中算法是计算Adapter中getView方法返回的View,但是子布局中的必须由LinearLayout组成,因为只有LinearLayout才有着measure()方法,如果使用其他的布局如RelativeLayout,在调用listItem.measure(0, 0);时就会抛异常,因为除LinearLayout外的其他布局的这个方法就是直接抛异常的。
二是Scrollview 嵌套ListView中,listview必须在Scrollview 的滚动至最顶部,在Activity计算窗口的高度时,是在listview没有填充数据时候就完成的,由于ScrollView嵌套listview时没有指定高度,所以ScrollView就会按照layout中定义的默认高度计算。
通常我就用自定义listview
public class ScrollListView extends ListView {
public ScrollListView(Context context) {
super(context);
}
public ScrollListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScrollListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
通过Listview中onMeasure方法重新去计算宽高。
就是手动设置listview的高度要注意。