-
Notifications
You must be signed in to change notification settings - Fork 778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2019-04-22:谈谈Android的事件分发机制? #35
Comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
当点击的时候,会先调用顶级viewgroup的dispatchTouchEvent,如果顶级的viewgroup拦截了此事件(onInterceptTouchEvent返回true),则此事件序列由顶级viewgroup处理。如果顶级viewgroup设置setOnTouchListener,则会回调接口中的onTouch,此时顶级的viewgroup中的onTouchEvent不再回调,如果不设置setOnTouchListener则onTouchEvent会回调。如果顶级viewgroup设置setOnClickListener,则会回调接口中的onClick。如果顶级viewgroup不拦截事件,事件就会向下传递给他的子view,然后子view就会调用它的dispatchTouchEvent方法。 |
This comment has been minimized.
This comment has been minimized.
1.触发过程:Activity->Window->DocerView->ViewGroup->View,View不触发再返回由父级处理依次向上推。 大体流程: 推荐一篇介绍非常详细的博客:https://www.jianshu.com/p/38015afcdb58 |
给大家举个形象的例子吧。ViewGroup相当于老板或者部门管理。View相当于员工。onTouchEvent相当于接业务。dispatechTouchEvent相当于处理任务。onIterceptTouchEvent相当于拦截任务。
现在模拟来业务了(点击事件)
|
责任链模式 |
|
事件来源:input -> window -> ViewRoot -> DecorView -> Activity -> ... |
View是没有onInterceptTouchEvent(拦截)的方法的 |
之前写过一篇文章回顾时间分发机制,希望能有补充。 |
1.当我们按下手指,ViewGroup的onInterceptTouchEvent会最先处理down事件。 |
当顶级的ViewGroup接收到事件消息之后,会调用dispatchTouchEvent 方法进行分发事件, |
事件分发的细节真的非常多,用老板员工的例子,最早开始看的时候我是没记住过。如果你只是看别人得出来的结论,那么十个人他能总结出十种自己的结论,看似好像明白了,过一段时间自己去看还是会忘记,所以我觉得想要真的明白就得自己去跟踪源码,然后用关键代码提炼成伪代码,打log看结果,做好笔记。由于你没法获得自己手机的系统源码,所以最好用模拟器来调试,用模拟器对应的sdk版本编译运行代码,自定义几个简单的View和ViewGroup,从ViewGroup的dispatchTouchEvent()方法处开始打断点。这里分享一个小技巧,如果你想要程序在执行到你自定义ViewGroup的dispatchTouchEvent()处暂停,可以在断点的condition处加上this.getClass().getSimpleName().equals("CustomViewGroup1");这样的条件语句。后续总结完毕,我会发文章出来给大家参考的,大家有问题可以互相交流,共同进步。 |
事件分发机制是责任链模式,先从顶层传到底层,再从底层传回顶层,如果中间被消费或拦截,则流程结束: |
① 驱动层 -> Framework 层 : 用户触摸 , 或按键 后 , 事件在硬件中产生 , 从 硬件驱动层 , 传递到 Framework 层 ; ② WMS -> View 层 : WindowManagerService ( 简称 WMS ) 将事件传递到 View 层 ; ③ View 层内部 : 事件在 View 的容器及下层容器 / 组件 之间传递 ; |
伪代码: 单指操作下的: // ViewGroup 的 dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean consume = false;
// DOWN 事件重置触摸状态
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mFirstTouchTarget = null;
}
boolean intercept = onInterceptTouchEvent(ev); // 拦截事件
if (!intercept) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// 查找 mFirstTouchTarget
for (View child : childs) {
if (mFirstTouchTarget!=null&&child.pointInView(ev.getX(), ev.getY()) && child.dispatchTouchEvent(ev)) {
// 初始化 mFirstTouchTarget 链表,并添加 child
mFirstTouchTarget = new TouchTarget(child);
break;
}
}
}
}
if (intercept || mFirstTouchTarget == null) {
consume = super.dispatchTouchEvent(ev); // 最终调用View.dispatchTouchEvent
} else {
consume = mFirstTouchTarget.child.dispatchTouchEvent(ev); // 分发给 mFirstTouchTarget
}
return consume;
}
// View 的 dispatchTouchEvent
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean consume = false;
if (this.mOnTouchListener != null) {
consume = mOnTouchListener.onTouch(this, ev);
}
if (!consume) {
consume = onTouchEvent(ev);
}
return consume;
} |
No description provided.
The text was updated successfully, but these errors were encountered: