| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android事件分发机制及滑动冲突解决方案 -> 正文阅读 |
|
[移动开发]Android事件分发机制及滑动冲突解决方案 |
在 Android事件分发流程网上关于事件分发机制的的博客很多很多,但是很多都是写个Demo然后贴一下输出的Log或者拿源码分析,然后一堆的注释和说明,读者可能很难读懂,或者是读懂之后,过不了多久便又忘记了。那么,今天我用一张图来总结一下Android整个事件分发机制的流程,如果你能在脑海里留下这张图, 记住分发机制的整个流程,再去阅读那些源码博客会不会更加的印象深刻呢!反正我是印象挺深刻的!好了,请看图!(自从记住了这张图,妈妈再也不用担心我被面试官虐啦!) ? 事件分发机制U形图 注释:
结合整个图来看,我们得出事件流走向的几个结论(希望读者专心的对比U型图来记这些结论,多看几遍,脑子有比较清晰的概念。)
以上这三个结论就代表了ACTION_DOWN事件的所有事件传递可能性,不知道读者对着U型流程图,有没有在头脑里有一个清晰的认识了呢。相信记住这三个结论之后,再去跟着源码理解,能更加对事件分发有深入的了解呢!OK,我们继续来看ACTION_MOVE和ACTION_UP是怎么传递的呢! 注意:上面讲解的都是针对ACTION_DOWN的事件,ACTION_MOVE和ACTION_UP在传递的过程中并不是和ACTION_DOWN 一样,你在执行ACTION_DOWN的时候返回了false,(case :ACTION_DOWN的返回值false,不是dispatchTouchEvent的返回值为false)后面一系列其它的action就不会再得到执行了。简单的说,就是当dispatchTouchEvent在进行事件分发的时候,只有前一个事件(如ACTION_DOWN)返回true,才会收到ACTION_MOVE和ACTION_UP的事件。 上面提到过了,事件如果不被打断的话是会不断往下传到叶子层(View),然后不断回传到Activity,dispatchTouchEvent 和 onTouchEvent 可以通过return true 消费事件,终结事件传递,而onInterceptTouchEvent 并不能消费事件,它相当于是一个分叉口起到分流导流的作用,ACTION_MOVE和ACTION_UP 会在哪些函数被调用,之前说了并不是哪个函数收到了ACTION_DOWN,就会收到 ACTION_MOVE 等后续的事件的。(因为要消费事件,才有ACTION_DOWN和ACTION_MOVE 发生,因此只考虑返回值为true的情况) 对于ACTION_MOVE和ACTION_UP在不同函数中的传递,有以下结论:
对于ACTION_MOVE、ACTION_UP终极总结: 滑动冲突解决方案介绍完了事件分发机制的基本流程,我们来看看滑动冲突。滑动冲突的基本形式分为两种,其他复杂的滑动冲突都可以拆成这两种基本形式:
先来看第一种, 滑动方向不一致的情况。举个例子, 比如你用ViewPaper和Fragment搭配,而Fragment里往往是一个竖直滑动的ListView这种情况是就会产生滑动冲突,但是由于ViewPaper本身已经处理好了滑动冲突,所以我们无需考虑,不过若是换成ScrollView,我们就得自己处理滑动冲突了。图示如下: ? 滑动方向不一致的情况 再看看第二种,这种情况下,因为内部和外部滑动方向一致,系统会分不清你要滑动哪个部分,所以会要么只有一层能滑动,要么两层一起滑动得很卡顿。图示如下: ? 滑动方向一致的情况 对于这两种情况,我们有不同的方法来处理它。 第一种:第一种的冲突主要是一个横向的,一个竖向的,所以在开发中我们只要判断滑动方向是竖向还是横向的,再让对应的View滑动即可。判断的方法有很多,比如竖直距离与横向距离的大小比较,哪个距离大就判定为向哪个方向滑动的;滑动路径与水平形成的夹角等等。 第二种:对于这种情况,比较特殊,我们没有通用的规则,得根据业务逻辑来得出相应的处理规则。举个最常见的例子,ListView下拉刷新功能,需要ListView自身滑动实现滑动,但是当滑动到头部时需要ListView和Header一起滑动,也就是整个父容器的滑动,这就涉及到滑动冲突问题了,如果不处理好滑动冲突,就会出现各种意想不到情况。对于这种情况的解决,我们可以采用拦截法:
? 外部拦截法 代码注释: a:首先down事件父容器必须返回false ,因为若是返回true,也就是拦截了down事件,那么后续的move和up事件就都会传递给父容器(onTouchEvent),子元素就没有机会处理事件了。 b:其次是up事件也返回了false,一是因为up事件对父容器没什么意义,其次是因为若事件是子元素处理的,却没有收到up事件会让子元素的onClick事件无法触发。
首先我们需要重写子元素的dispatchTouchEvent方法: ? dispatchTouchEvent方法 然后修改父容器的onInterceptTouchEvent方法: ? 父容器的onInterceptTouchEvent方法 滑动冲突解决实战
看代码看不出所以然,我们通过实例来看看滑动冲突是怎么样的。我们先模拟第一种场景,内外滑动方向不一致,我们先自定义一个父控件,让其可以左右滑动,类似于ViewPaper: ? 内外滑动方向不一致 然后在布局中添加listview ? 添加listview之后的界面 可以看到左右滑动确实失效了,说明确实产生了滑动冲突。那么我们就来解决一下吧!首先我们要明白滑动规则是什么,这个例子中如果我们竖直滑动就让ListView消耗事件进行滑动,水平滑动就让我们自定义的父容器滑动。 首先用外部拦截法,我们需要重写onInterceptTouchEvent方法,代码如下: ? 外部拦截法 这里我们判断横向滑动的距离与竖直滑动距离的长短。若是竖直滑动的长,则判断为竖直滑动,那么就是ListView的滑动,就将intercepted置为false,让父容器不拦截,交由子元素ListView处理。若是横向,则intercepted置为true,交由父容器处理。OK,完美解决滑动冲突问题,效果图: ? 最终效果图 接下来看看内部拦截法:重写其dispatchTouchEvent方法: ? dispatchTouchEvent方法 再重写外部父容器的oninterceptTouchEvent方法: ? 父容器的oninterceptTouchEvent方法
接下来看看同方向的滑动冲突,这里我们用一个竖直的ScrollView嵌套一个ListView做例子。首先看看没有解决滑动冲突的时候是咋样的: ? 滑动方向一致的情况 我们看到只要ScrollView可以滑动,内部的ListView是不能滑动的。那我们现在来解决这个问题,同向滑动冲突和与不同向滑动冲突不一样,得根据实际的需求来确定拦截的规则。 这里我们的需求是当ListView滑到顶部了,并且继续向下滑就让ScrollView拦截掉;当ListView滑到底部了,并且继续向下滑,就让ScrollView拦截掉,其余时候都交给ListView自身处理事件。 首先用外部拦截法,我们需要重写ScrollView的onInterceptTouchEvent方法,代码如下: ? 外部拦截法 这里我们看到Down事件里我们并没有返回false而是返回super.onInterceptTouchEvent(event),这是因为ScrollView在Down方法时需要初始化一些参数如果我们直接返回false,会导致滑动出现问题。并且前面说过ViewGroup的onInterceptTouchEvent方法是默认返回false的,所以我们这里要返回super方法才可。OK,完美解决,效果图就不贴出来了,你懂的。 接下来看看内部拦截法:先重写ScrollView的onInterceptTouchEvent方法,让其拦截除了Down事件以外的其他方法: ? 父容器的onInterceptTouchEvent方法 在重写ListView的dispatchTouchEvent方法,规则已经说明过了: ? listview的dispatchTouchEvent方法 效果图: ? 最终效果图 最终实现了完美解决滑动冲突。 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 7:56:35- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |