Android读书笔记---View事件的分发机制(一)

(内容来自于Android开发艺术探索)
点击事件的分发过程,其实就是MotionEvent事件的发布过程。当事件发生后,系统需要将事件传到一个View上。
事件的传递过程是Activity–>Window–>顶级View(setContentView设置的View)。

分发一个点击事件由三个方法协作完成
1.public boolean dispatchTouchEvent(MotionEvent ev)
事件的发布。返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent影响。
2.public boolean onInterceptEvent(MotionEvent ev)
在上述方法内部调用,返回结果表示是否拦截次事件,
3.public boolean onTouchEvent(MotionEvent event)
处理该事件,返回结果表示是否消耗该事件,是否处理该事件

例如:当一个事件通过ViewGroup是(事件首先会通过父级容器向下分配),会调用它的dispatchTouchEvent方法,在dispatchTouchEvent方法中,如果 onInterceptEvent方法返回结果为true,则表示事件由它处理,进而会继续调用onTouchEvent方法,如果onInterceptEvent方法返回false,则会传给子view,子view的dispatchEvent方法调用,子view通过onInterceptionEvent方法继续判断是否拦截。
注:当一个View实现了onTouchListener,并且重写了onTouchEvent方法时,事件处理的优先级看onTouchListener中onTouch回调方法的返回值,如果返回false,则代表onTouchListener不处理,交给onTouchEvent方法处理,所以onTouchListener的优先级高于onTouchEvent.
当一个事件产生时,所有子View的onTouchEvent方法都返回false,既不处理该事件,事件最终会回抛给Activity层来处理。(所以源码中,所有View的onTouchEvent事件返回都是false,Activity中返回false)。

事件机制的总结:
1.一系列的事件都是从down—>move..move…–>up
的。称之为一个事件序列
2.一个事件序列理论上只能被一个View拦截
3.一旦拦截一个事件序列中的某一次事件,down—>move..move…–>up之中任何一次事件。所有的事件都会交由该View处理。
4.一旦一个View接收了事件,必须消耗ACTION_DOWN事件(onTouchEvent返回了false就代表不对ACTION_DOWN事件做处理,也代表不对这一事件序列做处理),否则之后的事件都会再返回给父元素,再调用父元素的onTouchEvent方法进行处理,就好比上级交给你做一件事情,开头都没有做好,上级不高兴就不让你做,收回了命令,交给其他人或者自己做了。
例子:下面是一个处理ViewPager滑动事件的例子

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        ViewPager mViewPager = getTouchViewPager(mViewPagers, ev);
        Log.i(TAG, "mViewPager = " + mViewPager);
        //判断是否拦截此次事件
        if (mViewPager != null && mViewPager.getCurrentItem() != 0) {
//默认返回false
         return super.onInterceptTouchEvent(ev);
        }

        switch (ev.getAction()) {
            //当只是按下去是,既非滑动事件,不对此事件做处理
            case MotionEvent.ACTION_DOWN:
                downX = tempX = (int) ev.getRawX();
                downY = (int) ev.getRawY();
                break;
            //当移动时拦截次事件
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) ev.getRawX();

                if (moveX - downX > mTouchSlop
                        && Math.abs((int) ev.getRawY() - downY) < mTouchSlop) {
                    return true;
                }
                break;
        }

        return super.onInterceptTouchEvent(ev);
    }

onTouchEvent事件的处理

//down事件,因为onTouchEvent返回了true 所以代表处理过了
 // up,和move部分进行了分别的处理
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                int moveX = (int) event.getRawX();
                int deltaX = tempX - moveX;
                tempX = moveX;
                if (moveX - downX > mTouchSlop
                        && Math.abs((int) event.getRawY() - downY) < mTouchSlop) {
                    isSilding = true;
                }

                if (moveX - downX >= 0 && isSilding) {
                    mContentView.scrollBy(deltaX, 0);
                }
                break;
            case MotionEvent.ACTION_UP:
                isSilding = false;
                if (mContentView.getScrollX() <= -viewWidth / 2) {
                    isFinish = true;
                    scrollRight();
                } else {
                    scrollOrigin();
                    isFinish = false;
                }
                break;
        }

        return true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值