Android中的事件分发(上)
来源:互联网 发布:管道保温计算软件 编辑:程序博客网 时间:2024/06/10 08:43
不用我多说,相信大家都知道事件分发的重要性吧。它是Android知识体系中重要的一部分,当然对于初学Android的人来说是比较难的一部分,但是又不能不学,因为它是解决滑动冲突的理论基础,而且面试的时候面试官非常喜欢问这部分内容。
我不会单单的贴贴源码,我也不会单单的写个Demo打打Log,我也不会单单的写写结论。因为这篇文章里源码、log、结论都有……(哈哈开个玩笑),我觉得学习事件分发不能靠背背结论,看看别人写的流程图就算了,而是真的要看看源码写写Demo体会一下,这样才会有深刻的认识。
好了,废话就不说了,下面谈谈事件分发吧。本文主要谈View的事件分发。
我们先来写个栗子,就是给一个Button设置setOnTouchListener和setOnClickListener,其中onTouch是有返回值的,默认返回false。下面我们打一下log:
那么我们修改onTouch返回值为true后:
那么我们暂时可以得到两个小结论:
- onTouch先于onClick被触发
- 如果onTouch返回值为true,那么onClick便不会被触发
下面我们再写个栗子,写个MyButton类继承Button,重写dispatchTouchEvent和onTouchEvent方法。暂时并不加任何其它代码,只是打一下log:
onTouch返回值为true:
onTouch返回值为false:
如果修改dispatchTouchEvent返回值为false(这里onTouch返回true时):
@Overridepublic boolean dispatchTouchEvent(MotionEvent event){ Log.d("-------MyButton-------","----dispatchTouchEvent----"+event.getAction()); // return super.dispatchTouchEvent(event); super.dispatchTouchEvent(event); return false;}
我们可以看到当dispatchTouchEvent返回值为false时,Button已经接收不到move、up事件了。而是传递给了它的父控件。
好了两个栗子到此结束,等我们看完了源码再回来看栗子吧。。
View的事件分发涉及到dispatchTouchEvent和onTouchEvent两个方法,我们先看dispatchTouchEvent的源码:
public boolean dispatchTouchEvent(MotionEvent event){ //......省略 if (onFilterTouchEventForSecurity(event)) { //noinspection SimplifiableIfStatement ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null&& (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) { result = true; } if (!result && onTouchEvent(event)) { result = true; } } //.......省略 return result; }
这里是dispatchTouchEvent的关键代码,我们看一下第二个if语句:
- 条件一:只要我们对View设置了Listener,那么li!=null
- 条件二:只要我们对控件设置了setOnTouchListener事件,则条件二为true
- 条件三:该View是否是enabled
- 条件四:onTouch的返回值,其实这里可以看做是先执行onTouch,再判断返回值
再看一下第三个if语句,如果没有进入第二个if语句并且onTouchEvent返回值为true,才会进入第三个if里面。
其实两个if语句里只有一句代码,就是修改了一个boolean类型变量值,我们可以把dispatchTouchEvent源码修改下更容易理解:
public boolean dispatchTouchEvent(MotionEvent event){ //......省略 if (li != null && li.mOnTouchListener != null&& (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) { return true; } //.......省略 return onTouchEvent(event); }
暂时可以得到下面几个结论:
- 假设View设置了setOnTouchListener,如果onTouch返回值为true,那么onTouchEvent不会被调用;如果onTouch返回值为false,那么onTouchEvent会被调用,此时onTouch也是会被调用的,这点要注意。
- 如果该View是disenabled的,那么onTouch不会被调用,但是onTouchEvent会被调用。
- 注意分析dispatchTouchEvent的返回值,跟onTouch或者onTouchEvent有关系。
那么onClick是在哪里被调用的呢?别着急,我们先看看接着上面去看看onTouchEvent的源码,我们可以看到有个方法performClick(),其实是在这里面触发的onClick
public boolean performClick() { final boolean result; final ListenerInfo li = mListenerInfo; if (li != null && li.mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); li.mOnClickListener.onClick(this); result = true; } else { result = false; } sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); return result;}
现在我们对各个方法和结论再总结一下:
- 同一个事件序列包括down事件、n个move事件、up事件。
- 事件分发的顺序为dispatchTouchEvent–>onTouch–>onToucEvent
- dispatchTouchEvent方法是控制事件分发的,返回值为true时表示中止down事件的分发,同事件序列的move、up事件会传递给该控件;返回值为false时表示不中止down事件的分发,这个事件该控件不要,同事件序列的move、up事件不会传递给该控件。
- 当onTouchEvent被调用,它的返回值就是dispatchTouchEvent的返回值。
好了,View的事件分发大概就写这么多了,其实还有更多的结论,但是都可以通过源码分析出来,这里不过多介绍了。如有错误,欢迎指正。
- Android中的事件分发(上)
- android事件分发上
- Android中的事件分发
- Android 事件分发机制(上)
- Android事件分发完全解析(上)
- Android事件分发机制(上)
- android事件分发源码解析(上)
- Android(View)事件分发机制上
- Android中的事件分发机制(上)——ViewGroup的事件分发
- Android中的事件分发机制(一)
- Android事件分发机制 上
- android中的事件分发机制
- Android中的事件分发机制
- Android中的事件分发机制
- Android中的事件分发机制
- Android中的View事件分发
- Android中的事件分发机制
- Android中的事件分发总结
- DataBinding使用教程(一):配置与基本使用
- linux卸载openjdk以及安装正常版本jdk
- 浙大PAT甲级-1008
- Machine Learning----Regression(2)
- haproxy.cfg配置详解
- Android中的事件分发(上)
- 文件上传与下载
- 关于解决工程编译出现Undefined symbol __use_two_region_memory 和Undefined symbol __initial_sp的问题
- Spring初始化
- CRC循环冗余码
- 【Linux】进程间的关系以及终端的概念
- 人生不是只有努力就够了
- LK概览
- redis哨兵模式使用lua脚本实现分布式锁