Android ListView+ScrollView显示和触摸冲突解决

  • Post author:
  • Post category:其他


最近在项目中碰到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 版权协议,转载请附上原文出处链接和本声明。