Android View滑动冲突解决方案

文章目录

  • 前言
  • 1. 滑动冲突
  • 2. 解决方案
    • 2.1 外部解决法
    • 2.2 内部拦截法
  • 参考资料

前言

本文需要读者对View事件分发的流程有基本的了解,如果还未完全理解事件分发流程的,需要先学习相关部分内容,这部分可以参考我的上一个博客:

Android View点击事件分发原理,源码解读
https://blog.csdn.net/qq_41872247/article/details/139880308

前提:
现在来说我们如果是使用Google官方的View嵌套,比如ViewPager2,ScrollView,RecyclerView等滑动视图的话,哪怕你出现了两个滑动视图嵌套的情况,一般来说也不会出现滑动冲突的场景,因为Google官方经过多年的迭代之后,对于自带的这些视图常用场景的处理都已经很完善了。

已经实测过不会出现滑动冲突的场景(不分先后顺序):

  1. RecyclerView套RecyclerView
  2. ScrollView套RecyclerView
  3. ViewPager2套RecyclerView
  4. ViewPager2套ScrollView,ScrollView套ViewPager2

所以,想要讲述滑动冲突这个问题怎么解决,最需要的是先有一个冲突的场景案例。

1. 滑动冲突

一般而言,滑动冲突只有以下三种场景。

  1. 内部控件的滑动方向和外部控件的滑动方向不同(比如内部视图是左右滑动,而外部视图是上下滑动)
  2. 内部控件的滑动方向和外部控件的滑动方向相同(比如内部视图和外部视图都是上下滑动)
  3. 前两者结合的嵌套滑动问题。

2. 解决方案

我们在处理滑动冲突的时候,无非都是遵循一个原则:
当用户想要操作里面那个视图的滑动功能时,让里面的视图处理掉滑动点击事件。
当用户想要操作外面那个视图的滑动功能时,让外面的视图处理掉滑动点击事件。

基于这两种场景,我们在处理滑动冲突的时候就有了外部解决法和内部解决法。
对于滑动方向不同的场景,用外部解决法比较容易写代码
对于滑动方向相同的场景,用内部解决法比较容易写代码

2.1 外部解决法

在外部视图的onInterceptTouchEvent进行逻辑判断,如果是父布局需要滑动,就拦截该事件,否则就放过该事件,代码如下:

override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {when (ev?.action) {MotionEvent.ACTION_DOWN -> {return false}MotionEvent.ACTION_MOVE -> {if (这是父布局的滑动事件) {return true} else {return false}}MotionEvent.ACTION_UP,MotionEvent.ACTION_CANCEL -> {return false}}return super.onInterceptTouchEvent(ev)
}

2.2 内部拦截法

想要让子布局达成这个条件,就需要两点:

  1. 让子布局处理滑动逻辑的视图,确实的消化掉滑动事件,也就是让内部View处理dispatchTouchEvent这个方法最终return true。
  2. 让父布局跳过处理滑动逻辑的视图,不拦截该事件,好让事件确实的能流到内部的视图中而不是被外部视图直接处理,也就是让父布局的拦截方法onInterceptTouchEvent这个方法return false。

对于内部拦截法而言,由于他不直接修改父布局的onInterceptTouchEvent方法,所以他需要另外一个API:parent.requestDisallowInterceptTouchEvent(),用这个API来变相控制父布局的onInterceptTouchEvent返回true或false

同时要注意,由于点击事件的延续性,无论这个滑动事件最终是父布局处理还是子布局处理,最开始的DOWN事件父布局不要拦截,子布局在DOWN事件固定return true。

他的大体代码结构如下:

override fun dispatchTouchEvent(event: MotionEvent?): Boolean {when(event?.action) {MotionEvent.ACTION_DOWN -> {parent.requestDisallowInterceptTouchEvent(true)}MotionEvent.ACTION_MOVE -> {if (这是子布局的滑动事件)parent.requestDisallowInterceptTouchEvent(true)elseparent.requestDisallowInterceptTouchEvent(false)}MotionEvent.ACTION_CANCEL,MotionEvent.ACTION_UP -> {parent.requestDisallowInterceptTouchEvent(false)}}// 如果是子布局的滑动事件,一定要保证该方法return true,这证明了子视图确实的消费了该点击事件// 这样父布局才不会重复处理该事件,引起滑动冲突// 由于点击事件的延续性,DOWN固定return trueif (这是子布局的滑动事件 || event?.action == MotionEvent.ACTION_DOWN)super.dispatchTouchEvent(event)return trueelse return super.dispatchTouchEvent(event)
}

参考资料

https://blog.csdn.net/wekajava/article/details/120623229

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/40389.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Postman使用教程

传统接口风格 RESTful风格 使用Postman完成测试用例目标: Postman教程 (1)准备工作,下载Postman新建 (2)登录接口调试-获取验证码 (3)登录接口调试-登录 (4)…

线程的联合

当前线程邀请调用方法的线程优先执行,在调用方法的线程执行结束之前,当前线程不能再次执行。线程A在运行期间,可以调用线程B的join()方法,让线程B和线程A联合。这样,线程A就必须等待线程B执行完毕后,才能继…

Mysql查询IFNULL和想象的不一样

select sum(ifnull(a,0)) aaa,ifnull(sum(a),0) bbb from (select g.goodsid a from goods g where g.goodsid 601 ) tmp #注意 goodsid 601 的不存在 ​​​ 返回的结果和想象中不同,解释如下 在您SQL查询中,创建了一个子查询(别名为tmp&a…

【深度解析】滑动窗口:目标检测算法的基石

标题:【深度解析】滑动窗口:目标检测算法的基石 目标检测是计算机视觉领域的一个核心任务,旨在识别图像中所有感兴趣的目标,并确定它们的位置和大小。滑动窗口方法作为目标检测中的一种传统技术,虽然在深度学习时代逐…

Linux 操作系统详解

前言 Linux 是一个强大且开源的操作系统,以其稳定性、灵活性和安全性广受欢迎。它在个人计算机、服务器、嵌入式系统以及超级计算机等多个领域得到广泛应用。本文将从多个角度深入探讨 Linux 的历史、架构和主要特性,为初学者和专业人士提供全面的理解和…

Linux_管道通信

目录 一、匿名管道 1、介绍进程间通信 2、理解管道 3、管道通信 4、用户角度看匿名管道 5、内核角度看匿名管道 6、代码实现匿名管道 6.1 创建子进程 6.2 实现通信 7、匿名管道阻塞情况 8、匿名管道的读写原子性 二、命名管道 1、命名管道 1.1 命名管道通信 …

国内外大模型集合

为了满足日益增长的AI需求,我们精心打造了一站式大模型导航网站,旨在成为连接您与全球顶尖人工智能模型的桥梁。无论您是科研工作者、开发者还是对AI充满好奇的探索者,这里都有您所需。 国内大模型精选 通义千问 —— 阿里巴巴集团倾力打造…

某业帮六月校招后端笔试

题目一 解题思路 签到题,dp就行。 题目二 解题思路 这个比较烦人,需要处理额外的引号和括号。用DFS,对于每个间隙,插入与不插入都搜一遍。 题目三 解题思路: 双指针,左右各一个指针,对比长度&…

OpenLCA、GREET、R语言的生命周期评价方法、模型构建

原文链接:OpenLCA、GREET、R语言的生命周期评价方法、模型构建教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247608240&idx6&sn1b5758206d500399fe7cc69e800f61fe&chksmfa826657cdf5ef413d31557941a1c5db5cc84bba8d0f408c469e05a4118c…

#LinuxC高级 笔记一

linux命令 什么是嵌入式? 以应用为中心,以计算机技术为基础,软件硬件可裁剪,适用于对功能、可靠性、成本、体积、功耗有严格要求的专用计算机系统 计算机系统组成? 硬件、软件 操作系统? ios windows harmo…

k8s_集群搭建_k8s管理前端_dashboard安装部署---分布式云原生部署架构搭建017

然后再去安装一下一个dashboard,有了这个以后,操作k8s集群就不用 一直敲命令了 可以看到上面的命令拿过来,然后 执行就可以了 然后如果执行慢,可以直接先去下载,使用wget,然后再去 也可以在浏览器访问,把内容拿到,然后 下面是内容: # Copyright 2017 The Kubernetes Author…

登 Cell 子刊!清华大学张强锋课题组开发 SPACE 算法,组织模块发现能力领先同类工具

多细胞生物中的细胞尽管共享相同的基因组,但因其内部基因调控网络的差异以及与周围微环境中相邻细胞的外部信号交流,使得它们在形态、基因表达和功能上展现出显著的多样性。为了将细胞类型信息与其在组织内的空间位置相关联,空间转录组学 (Sp…

Vue86-Vuex中的getters属性

一、getters的使用 1-1、index.js中getters的书写 计算属性computed靠return获得返回值! 1-2、组件中getters的调用 state是数据源,getters是拿着数据源里的东西进行一番加工。像极了:data和computed 二、小结

vue 启动项目报错Syntax Error: Error: PostCSS received undefined instead of CSS string

启动vue项目然后报错如下图 这个是跟node版本有关系 因为要开发不同的项目使用不同的node版本,所以就用nvm切换,所以导致了node-sass编译问题 执行这个命令就可以 npm install node-sass or npm rebuild node-sass node-sass对于node高版本和低版本切…

智能胎教仪,科技与教育的融合-N9301胎教仪语音方案

随着科学技术的不断进步,人们对婴幼儿教育的认知也日趋成熟和全面。其中,胎教作为一种重要的早期教育方式,近年来备受瞩目。而胎教仪语音芯片的研发,正是为了满足这一需求,为胎儿的健康成长提供更加便捷的胎教方案。 一…

Tomcat服务部署安装

一、Tomcat基础 1.Tomcat简介 Tomcat服务器是一个免费的开放源代码的Web应用服务器,Tomcat虽然和Apache或者Nginx这些Web服务器一样,具有处理HTML页面的功能,然而由于其处理静态HTML的能力远不及Apache或者Nginx,所以Tomcat通常…

Linux 程序置顶脚本

引言 当希望我们运行的程序,一直保持在最顶端运行,即置顶状态,那么有很多种方式,这边给出一种脚本方式处理。 通过持续监控,当发现活动窗口不是我们所希望的窗口时,将我们希望置顶的程序窗口置顶。 脚本 …

力扣:3195. 包含所有 1 的最小矩形面积 I(Java)

目录 题目描述:示例 1:示例 2:代码实现: 题目描述: 给你一个二维 二进制 数组 grid。请你找出一个边在水平方向和竖直方向上、面积 最小 的矩形,并且满足 grid 中所有的 1 都在矩形的内部。 返回这个矩形可…

LLama-Factory大模型训练框架,基于自己数据集微调qwen7B模型实战

一,项目简介 LLama-Factory,大模型训练框架,支持多种模型,多种训练方式, 项目github地址:link 项目特色 多种模型:LLaMA、LLaVA、Mistral、Mixtral-MoE、Qwen、Yi、Gemma、Baichuan、ChatGL…

“LNMP环境搭建实战指南:从零开始配置CentOS 7下的Nginx、MySQL与PHP“

目录 1.前言 2.准备工作 2.1.环境信息 2.2.关闭SELinux和firewalld 3.安装Nginx 3.1.运行以下命令,安装Nginx 3.2.运行以下命令,查看Nginx版本 4.安装MySQL 4.1.更新秘钥 4.2.配置MySQL的YUM仓库 4.3.安装MySQL 4.4.查看MySQL版本 4.5.启动…