最近在项目中碰到ListView+ScrollView这个需求,发现会产生两个冲突:
1.在ScrollView中ListView显示不全的冲突
2.ScrollView和ListView触摸事件的冲突
正文:
网上查了很多资料,发现冲突1原来是ScrollView中的ListView无法计算的高度导致的,解决这个冲突的方法之一是只要调用list条目的measure方法,重新计算高度即可。
public static void setListViewHeightBasedOnChildren(ListView listView,boolean isLast) {
if (listView == null)
return;
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null)
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();
if(isLast){
//因为我的项目底部还有个菜单栏,判断是最后一个listview就加上底部的高度,没有的话可以不加
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1))+dip2px(50);
}else{
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
}
//重新设置listView的高度
listView.setLayoutParams(params);
}
经过这样,ListView就能正常显示了,但是还有一个冲突时触摸事件的问题。有几种情况:
1.内部ListView不需要点击事件
2.ListView需要点击事件
第一种情况比较好解决,直接让ScrollView拦截所有触摸事件即可。在自定义ScrollView中,在里面重写onInterceptTouchEvent(MotionEvent ev)方法
public boolean onInterceptTouchEvent(MotionEvent ev) {
float x = 0;
float y = 0;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
x = ev.getX();
y = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
float currX = ev.getX();
float currY = ev.getY();
float dx = Math.abs(currX-x);
float dy = Math.abs(currY-y);
x = currX;
y = currY;
if(dx>dy){
//水平移动不拦截
return false;
}
}
return true;
}
第二种情况需要重写ListView的dispatchTouchEvent(MotionEvent ev)方法
float x = 0;
float y = 0;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
x = ev.getX();
y = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
float currX = ev.getX();
float currY = ev.getY();
float dx = Math.abs(currX - x);
float dy = Math.abs(currY - y);
x = currX;
y = currY;
if (dx <= 5 && dy <= 5) {
//小范围移动或点击也由父类分发事件
return super.dispatchTouchEvent(ev);
} else if (dx > dy) {
//水平移动由父类分发事件
return super.dispatchTouchEvent(ev);
} else {
//listview不处理事件
return false;
}
}
return super.dispatchTouchEvent(ev);
至此,ListView和ScrollView两个冲突都被解决完成。
版权声明:本文为nilielie原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。