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

来源:互联网 发布:五线谱识谱软件 编辑:程序博客网 时间:2024/06/06 01:48

(内容来自于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
原创粉丝点击