Android事件分发机制简记

来源:互联网 发布:漫画软件推荐 编辑:程序博客网 时间:2024/06/08 17:22

基础认知

  • 当用户触摸屏幕时(View或ViewGroup派生的控件),将产生点击事件(Touch事件)

    • Touch事件相关细节(发生触摸的位置、时间、历史记录、手势动作等)被封装成MotionEvent对象
  • 主要发生的Touch事件有如下四种

    • MotionEvent.ACTION_DOWN:按下View(所有事件的开始)

    • MotionEvent.ACTION_MOVE:滑动View

    • MotionEvent.ACTION_CANCEL:非人为原因结束本次事件

    • MotionEvent.ACTION_UP:抬起View(与DOWN对应)

  • Android的UI界面是由Activity、ViewGroup、View及其派生类组合而成的

  • View是所有UI组件的基类

    • 一般Button、ImageView、TextView等控件都是继承父类View
  • ViewGroup是容纳UI组件的容器,即一组View的集合(包含很多子View和子VewGroup)

    • 其本身也是从View派生的,即ViewGroup是View的子类

    • 是Android所有布局的父类或间接父类:项目用到的布局(LinearLayout、RelativeLayout等),都继承自ViewGroup,即属于ViewGroup子类。

    • 与普通View的区别:ViewGroup实际上也是一个View,只不过比起View,它多了可以包含子View和定义布局参数的功能。

  • Android事件分发机制的本质是要解决:点击事件由哪个对象发出,经过哪些对象,最终达到哪个对象并最终得到处理。

    • 这里的对象是指Activity、ViewGroup、View
  • Android中事件分发顺序:Activity(Window) -> ViewGroup -> View

  • 事件分发过程由dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()三个方法协助完成

Activity的事件分发机制

  • 当一个点击事件发生时,事件最先传到Activity的dispatchTouchEvent()进行事件分发,最终是调用了ViewGroup的dispatchTouchEvent()方法

  • 如果ViewGroup的dispatchTouchEvent()返回true就不执行Activity的onTouchEvent()方法;如果返回false,就执行。

  • 这样事件就从 Activity 传递到了 ViewGroup

ViewGroup事件的分发机制

  • Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View

  • 在ViewGroup中通过onInterceptTouchEvent()对事件传递进行拦截

    • onInterceptTouchEvent方法返回true代表拦截事件,即不允许事件继续向子View传递;

    • 返回false代表不拦截事件,即允许事件继续向子View传递;(默认返回false)

  • 子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。

View事件的分发机制

  • onTouch()的执行高于onClick()

  • 每当控件被点击时:

    • 如果在回调onTouch()里返回false,就会让dispatchTouchEvent方法返回false,那么就会执行onTouchEvent();

    • 如果回调了setOnClickListener()来给控件注册点击事件的话,最后会在performClick()方法里回调onClick()。

    • onTouch()返回false(该事件没被onTouch()消费掉) = dispatchTouchEvent()返回false(继续向下传递) = 执行onTouchEvent() = 执行OnClick()

    • 如果在回调onTouch()里返回true,就会让dispatchTouchEvent方法返回true,那么将不会执行onTouchEvent(),即onClick()也不会执行;

    • onTouch()返回true(该事件被onTouch()消费掉) = dispatchTouchEvent()返回true(不会再继续向下传递) = 不会执行onTouchEvent() = 不会执行OnClick()

思考点

  • onTouch()和onTouchEvent()的区别

    • 这两个方法都是在View的dispatchTouchEvent中调用,但onTouch优先于onTouchEvent执行。

    • 如果在onTouch方法中返回true将事件消费掉,onTouchEvent()将不会再执行。

    • 如果你有一个控件是非enable的,那么给它注册onTouch事件将永远得不到执行。对于这一类控件,如果我们想要监听它的touch事件,就必须通过在该控件中重写onTouchEvent方法来实现。

  • Touch事件的后续事件(MOVE、UP)层级传递

    • 如果给控件注册了Touch事件,每次点击都会触发一系列action事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP等)

    • 当dispatchTouchEvent在进行事件分发的时候,只有前一个事件(如ACTION_DOWN)返回true,才会收到后一个事件(ACTION_MOVE和ACTION_UP),即如果在执行ACTION_DOWN时返回false,后面一系列的ACTION_MOVE和ACTION_UP事件都不会执行

    • dispatchTouchEvent()和 onTouchEvent()消费事件、终结事件传递(返回true)而onInterceptTouchEvent 并不能消费事件,它相当于是一个分叉口起到分流导流的作用,对后续的ACTION_MOVE和ACTION_UP事件接收起到非常大的作用

      • 请记住:接收了ACTION_DOWN事件的函数不一定能收到后续事件(ACTION_MOVE、ACTION_UP)
    • 如果在某个对象(Activity、ViewGroup、View)的dispatchTouchEvent()消费事件(返回true),那么收到ACTION_DOWN的函数也能收到ACTION_MOVE和ACTION_UP

    • 如果在某个对象(Activity、ViewGroup、View)的onTouchEvent()消费事件(返回true),那么ACTION_MOVE和ACTION_UP的事件从上往下传到这个View后就不再往下传递了,而直接传给自己的onTouchEvent()并结束本次事件传递过程

0 0
原创粉丝点击