本期三篇文章目录(可点击跳转)
一. Android TouchEvent事件传递机制初识
二. android点击事件传递源码讲解(ViewGroup)
Android TouchEvent事件传递机制在android应用开发中很常见,但是很多人不了解,现自我总结如下:
在触发OnTouch事件的时候Android的GroupView会调用如下三个函数:
public boolean dispatchTouchEvent(MotionEvent ev) //用于事件的分发
public boolean onInterceptTouchEvent(MotionEvent ev) // 用于事件的拦截
public boolean onTouchEvent(MotionEvent ev) //处理事件
在Android中,有一类控件是中还可以包含其他的子控件,这类控件是继承于ViewGroup类,例如:ListView, Gallery, GridView,FrameLayout、LinearLayout。
还有一类控件是不能再包含子控件,例如:Button、TextView、EditText。
这些控件中分别拥有如下的函数
Activity类: Activity -------------包含方法:
dispatchTouchEvent(); onTouchEvent();
View容器(ViewGroup的子类):比如FrameLayout、LinearLayout……ListView、ScrollVIew……这些控件 -----------------包含方法:
dispatchTouchEvent(); onInterceptTouchEvent(); onTouchEvent();
View控件(非ViewGroup子类):比如Button、TextView、EditText……这些控件---------------- 包含方法:
dispatchTouchEvent(); onTouchEvent();
1)dispatchTouchEvent()
用来分派事件。
其中调用了onInterceptTouchEvent()和onTouchEvent(),一般不重写该方法
2)onInterceptTouchEvent()
用来拦截事件。--------->父View向子View传递
ViewGroup类中的源码默认返回false,表示不拦截该事件,事件将向下传递(传递给其子View),如果子View不是ViewGroup类的控件,则传递给它自己onTouchEvent去处理;
若重写该方法,返回true则表示拦截,事件将终止向下传递,事件由当前ViewGroup类来处理,就是调用该类的onTouchEvent()方法。
3)onTouchEvent()
用来处理事件。--------->子View向父View传递
返回true则表示事件已经被处理,事件将终止向上传递(父View);
返回false表示事件没有被处理,则把事件传递给其父View的onTouchEvent()方法来处理
注意点:ACTION_MOVE或者ACTION_UP发生的前提是该控件一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。也就是说onTouchEvent均返回false,也就是说事件始终没有被消费,那后续事件(ACTION_DOWN的ACTION_MOVE或者ACTION_UP)不会触发,后面demo中会提到。
4.示例
页面布局如下
很简单的三层,下面通过控制上面三个方法的返回,看事件的传递。
1)LinearLayoutOne,LinearLayoutTwo,MyTextView 的dispatchTouchEvent,onInterceptTouchEvent(MyTextView没有此方法),onTouchEvent均返回false,也就是说事件始终没有被处理,也就是抛给外层的activity的ontouchEvent去处理了,那后续事件(ACTION_DOWN的ACTION_MOVE或者ACTION_UP)也都不会触发。Log信息如下:
05-13 13:04:19.521 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutOne: LinearLayoutOne---dispatchTouchEvent---ACTION_DOWN
05-13 13:04:19.521 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutOne: LinearLayoutOne---onInterceptTouchEvent---ACTION_DOWN
05-13 13:04:19.521 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutTwo: LinearLayoutTwo---dispatchTouchEvent---ACTION_DOWN
05-13 13:04:19.521 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutTwo: LinearLayoutTwo---onInterceptTouchEvent---ACTION_DOWN
05-13 13:04:19.521 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MyTextView: MyTextView---dispatchTouchEvent---ACTION_DOWN
05-13 13:04:19.521 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MyTextView: MyTextView---onTouchEvent---ACTION_DOWN
05-13 13:04:19.522 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutTwo: LinearLayoutTwo---onTouchEvent---ACTION_DOWN
05-13 13:04:19.522 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutOne: LinearLayoutOne---onTouchEvent---ACTION_DOWN
05-13 13:04:19.522 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_DOWN
05-13 13:04:19.532 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:04:19.999 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:04:20.015 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:04:20.048 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:04:20.056 32126-32126/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_UP
运行结论:LinearLayoutOne,LinearLayoutTwo,MyTextView都只处理了ACTION_DOWN,其余的TouchEvent被外层的Activity处理了
2)LinearLayoutOne,MyTextView 的dispatchTouchEvent,onInterceptTouchEvent(MyTextView没有此方法),onTouchEvent均返回false,LinearLayoutTwo onInterceptTouchEvent返回true,此时ACTION_DOWN应该传递到LinearLayoutTwo 的onTouchEvent,而不是像下传递到MyTextView 的onTouchEvent。同样,onTouchEvent均返回false,也就是说事件始终没有被处理,也就是抛给外层的activity的ontouchEvent去处理了,那后续事件(ACTION_DOWN的ACTION_MOVE或者ACTION_UP)也都不会触发。Log信息如下:
05-13 13:19:22.413 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutOne: LinearLayoutOne---dispatchTouchEvent---ACTION_DOWN
05-13 13:19:22.413 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutOne: LinearLayoutOne---onInterceptTouchEvent---ACTION_DOWN
05-13 13:19:22.413 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutTwo: LinearLayoutTwo---dispatchTouchEvent---ACTION_DOWN
05-13 13:19:22.413 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutTwo: LinearLayoutTwo---onInterceptTouchEvent---ACTION_DOWN
05-13 13:19:22.414 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutTwo: LinearLayoutTwo---onTouchEvent---ACTION_DOWN
05-13 13:19:22.415 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.LinearLayoutOne: LinearLayoutOne---onTouchEvent---ACTION_DOWN
05-13 13:19:22.416 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_DOWN
05-13 13:19:22.434 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:19:22.503 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:19:22.518 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:19:22.552 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:19:22.567 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_MOVE
05-13 13:19:22.569 14442-14442/focus.teach.toucheventdemo I/focus.teach.toucheventdemo.MainActivity: MainActivity---onTouchEvent---ACTION_UP
运行结论:LinearLayoutOne,LinearLayoutTwo都只处理了ACTION_DOWN,其余的TouchEvent被外层的Activity处理了
其他的几种情况,可以自己去测试。
5.逻辑抽象
拿上面第二个示例,画出对应的逻辑图,如下所示:
[外链图片转存失败(img-nMtC9Vxp-1569079045194)(https://img-blog.csdn.net/20160513140734515)]
demo下载地址:
http://download.csdn.net/detail/dfskhgalshgkajghljgh/9525803
其他的逻辑图就不画了,有问题欢迎提出来。
欢迎一起交流讨论
群号:469890293