TouchEvent的传递机制

dispatchTouchEvent  分发事件
return false; //表示分发,默认false
return true; // 表示不分发;


onInterceptTouchEvent 拦截事件
dispatchTouchEvent  确认分发,会启动拦截事件;
return false; //表示不拦截,默认false
return true; // 表示拦截;
注意:拦截是相当于它的孩子(也就是说不会拦截自己,如果拦截,则TouchEvent会传到他自己,而它孩子就接收不)
不拦截会继续往他的孩子递归是否onInterceptTouchEvent ;


onTouchEvent  触摸事件
return false; //表示不消费,默认false
return true; // 表示消费;
onInterceptTouchEvent 确认拦截,会问自己是否要消费TouchEvent,
如果拦截了又不消费则,Touch结束;


invalidate():让整个view失效,这样view会被重新调用, 配合onDraw()使用;


事件的分发原理图:

图1:
图二:



案列: 分发的例子

下面红色框区域的结构是ScrollView, 它的孩子是一些TextView;
分析:
1.当点击它任意一个孩子(TextView)时,如果ScrollView不进行onInterceptTouchEvent ,则它就不可以在菜单上进行左右滑动;
2.但是如果拦截了全部,则它的孩子又会消费不了TouchEvent;


解决方法:
只有左右移动的时候进行拦截,这样父亲就拥有了TouchEvent,可在菜单上继续左右滑动,
而上下移动或静止的时候就不拦截,这样孩子又有了TouchEvent,那么孩子就可以点击了;

实例代码:
/**
 * 当滑动的时候,需要拦截TouchEvent时间,让scrollView消化,否则会分发到孩子去;
 * 当不滑动的停止的时候,不拦截,则会分发到孩子去,也就是TexView;
 */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
    // 只有水平滑动时才拦截touch
    case MotionEvent.ACTION_DOWN:
        startX = (int) (ev.getRawX() + 0.5f);
        startY = (int) (ev.getRawY() + 0.5f);
        break;
    case MotionEvent.ACTION_MOVE:
        int newX = (int) (ev.getRawX() + 0.5f);
        int newY = (int) (ev.getRawY() + 0.5f);
        int dx = Math.abs(startX - newX);
        int dy = Math.abs(startY - newY);
        if (dx > dy) {
            // 水平滑动,只有水平滑动才会dx.dy
            return true;
        }
        startX = (int) ev.getRawX();// 初始化当前位置
    case MotionEvent.ACTION_UP:
        break;
    }
    return super.onInterceptTouchEvent(ev);
}  










posted @ 2015-10-07 13:26  林锐波  阅读(302)  评论(0编辑  收藏  举报