3分钟搞定,学会Android滑动冲突解决技巧

前言

Android滑动冲突是Android开发中常见的问题。在一个界面中,可能存在多个View可以响应滑动事件。如果这些View滑动方向一致,则会导致滑动冲突。本文将从原理、使用与优化三个方面,详细介绍Android滑动冲突的解决方式。

滑动冲突的原理

Android的事件分发机制是基于ViewGroup的。当用户在屏幕上触摸时,事件会首先传递给最顶层的ViewGroupViewGroup会根据自己的滑动方向和滑动能力来决定是否拦截事件。如果ViewGroup拦截了事件,则事件不会传递给子View。如果ViewGroup没有拦截事件,则事件会传递给子View

如果子View也需要响应滑动事件,则子View需要重写onTouchEvent()方法来处理事件。子View可以通过requestDisallowInterceptTouchEvent()方法来告诉父ViewGroup不要拦截事件。

滑动冲突是指两个或多个View同时收到滑动事件,导致无法正常滑动。滑动冲突的原因有很多,例如:

  1. 两个View的滑动方向相同,例如RecyclerViewScrollView同时滑动。
  2. 两个View的滑动方向不同,但滑动范围重叠,例如HorizontalScrollViewWebView同时滑动。

解决方法

Android滑动冲突的主要解决思想有两种:外部拦截法和内部拦截法。

  • 外部拦截法:由父View拦截事件,然后根据需要将事件传递给子View
  • 内部拦截法:由子View拦截事件,然后根据需要将事件传递给父View

外部拦截法

外部拦截法是Android默认的滑动冲突解决方式。在这种方式下,父View会先拦截事件,然后根据需要将事件传递给子View

View可以通过重写onInterceptTouchEvent()方法来实现外部拦截法。在onInterceptTouchEvent()方法中,我们可以根据事件的类型和位置来判断是否需要拦截事件。如果需要拦截事件,则返回true,否则返回false

kotlin 复制代码
class CustomParentView(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs) {

    private var downX: Float = 0F
    private var downY: Float = 0F

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                downX = ev.x
                downY = ev.y
            }
            MotionEvent.ACTION_MOVE -> {
                val deltaX = ev.x - downX
                val deltaY = ev.y - downY

                // 根据滑动方向判断是否拦截事件
                if (Math.abs(deltaX) > Math.abs(deltaY)) {
                    return true
                }
            }
        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        // 处理滑动逻辑
        return true
    }

    // 其他相关代码
}

优点: 简单易用,适用于大多数滑动冲突问题。

缺点: 可能会导致父ViewGroup无法响应事件,例如父ViewGroup的子View正在滑动,而父ViewGroup的滑动事件也被拦截了。

内部拦截法

内部拦截法是指由子View拦截事件,然后根据需要将事件传递给父View

View可以通过重写dispatchTouchEvent()方法来实现内部拦截法。在dispatchTouchEvent()方法中,我们可以根据事件的类型和位置来判断是否需要拦截事件。如果需要拦截事件,则调用requestDisallowInterceptTouchEvent()方法来告诉父View不要拦截事件。

kotlin 复制代码
class MyView : View {

    // 通过重写 dispatchTouchEvent 方法实现内部拦截
    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action) {
            MotionEvent.ACTION_DOWN -> {
                // 按下时,禁止父View拦截事件
                parent.requestDisallowInterceptTouchEvent(true)
            }
            MotionEvent.ACTION_MOVE -> {
                // 根据业务逻辑判断是否拦截事件
                if (shouldInterceptTouchEvent(ev)) {
                    return true
                }
            }
            MotionEvent.ACTION_UP -> {
                // 手指抬起时,允许父View拦截事件
                parent.requestDisallowInterceptTouchEvent(false)
            }
        }
        return super.dispatchTouchEvent(ev)
    }

}

优点: 不会导致父ViewGroup无法响应事件,适用于父ViewGroup和子View都需要滑动的情况。

缺点: 需要重写子ViewdispatchTouchEvent()方法,可能会导致代码复杂。

注意事项和优化技巧

  • 在判断是否需要拦截事件时,需要考虑事件的方向、滑动距离等因素。
  • 如果父ViewGroup和子View都需要滑动,则可以使用事件分发机制来解决滑动冲突。
  • 避免过多的嵌套, 尽量减少布局的嵌套层次,以降低滑动冲突的概率。

总结

Android滑动冲突的解决方式主要有外部拦截法和内部拦截法两种。希望本文能帮助读者解决滑动冲突问题,提高Android开发水平。

推荐

android_startup: 提供一种在应用启动时能够更加简单、高效的方式来初始化组件,优化启动速度。不仅支持Jetpack App Startup的全部功能,还提供额外的同步与异步等待、线程控制与多进程支持等功能。

AwesomeGithub: 基于Github的客户端,纯练习项目,支持组件化开发,支持账户密码与认证登陆。使用Kotlin语言进行开发,项目架构是基于JetPack&DataBinding的MVVM;项目中使用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等流行开源技术。

flutter_github: 基于Flutter的跨平台版本Github客户端,与AwesomeGithub相对应。

android-api-analysis: 结合详细的Demo来全面解析Android相关的知识点, 帮助读者能够更快的掌握与理解所阐述的要点。

daily_algorithm: 每日一算法,由浅入深,欢迎加入一起共勉。

相关推荐
昨天;明天。今天。几秒前
案例-任务清单
前端·javascript·css
GEEKVIP1 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
zqx_71 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己1 小时前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称2 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色2 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2342 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河2 小时前
CSS总结
前端·css
model20053 小时前
android + tflite 分类APP开发-2
android·分类·tflite
BigYe程普3 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发