随笔 - 129,  文章 - 3,  评论 - 50,  阅读 - 15万

滑动冲突

有时候 viewpager 嵌套 webview 后,左右滑动冲突,直接消费或者处理拦截导致上下不能滑动,所以需要根据滑动情况判断处理,只在上下滑动时判断事件交给子view

复制代码
class ScrollWebView(context: Context, attrs: AttributeSet) : WebView(context, attrs) {

    private var mSlop = 0
    private var mDownY = 0f

    init {
        mSlop = ViewConfiguration.get(context).scaledTouchSlop
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event?.action) {
            MotionEvent.ACTION_DOWN -> mDownY = event.y
            MotionEvent.ACTION_MOVE -> {
                val off = mDownY - event.y
                if (abs(off) >= mSlop) {
                    parent.requestDisallowInterceptTouchEvent(true)
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                parent.requestDisallowInterceptTouchEvent(false)
            }
        }
        return super.onTouchEvent(event)
    }
}
复制代码

举一反三,很多滑动冲突都可以类似解决,至于是对父容器处理,还是子节点处理,根据情况来定

又比如在 viewpager 下嵌套 Recyclerview,Recyclerview 中又嵌套 viewpager 或者 Recyclerview,此时子 view 左右滑动起了冲突,这个确实不怪业务逻辑复杂了,只能自定义解决了

复制代码
class NestedViewPager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) {

    private var x1 = 0f
    private var y1 = 0f
    private var isScroll = false

    override fun dispatchTouchEvent(evt: MotionEvent?): Boolean {
        evt?.let {
            when (evt.action) {
                MotionEvent.ACTION_DOWN -> {
                    x1 = evt.x
                    y1 = evt.y
                    isScroll = false
                }
                MotionEvent.ACTION_MOVE -> {
                    // 通知其父控件不拦截
                    val x2 = evt.x
                    val y2 = evt.y
                    if (x1 - x2 > 1) {
                        //str = "向右滑"
                        parent.requestDisallowInterceptTouchEvent(true)
                        isScroll = false
                    } else if (x2 - x1 > 1) {
                        //str = "向左滑"
                        parent.requestDisallowInterceptTouchEvent(true)
                        isScroll = false
                    } else if (y1 - y2 > 100) {
                        parent.requestDisallowInterceptTouchEvent(false)
                        //str = "向上滑"
                        isScroll = true
                    } else if (y2 - y1 > 100) {
                        parent.requestDisallowInterceptTouchEvent(false)
                        //str = "向下滑"
                        isScroll = true
                    }
                }
                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                    if (isScroll) {
                        parent.requestDisallowInterceptTouchEvent(false)
                    } else {
                        parent.requestDisallowInterceptTouchEvent(true)
                    }
                }
            }
        }
        return super.dispatchTouchEvent(evt)
    }

}
复制代码

依然一顿梭哈解决,但是能不自定义就别自定义,特别是复杂的定义

这种滑动可以适配很多滑动冲突,比如 viewpager 下,嵌套了一个横向 Recyclerview,此时横向滑动很容易会触发 viewpager 的滑动,导致不丝滑,还是一样的处理

复制代码
class ScrollRecyclerView(context: Context, attrs: AttributeSet) : RecyclerView(context, attrs) {

    private var x1 = 0f
    private var y1 = 0f
    private var isScroll = false

    override fun dispatchTouchEvent(evt: MotionEvent?): Boolean {
        evt?.let {
            when (evt.action) {
                MotionEvent.ACTION_DOWN -> {
                    x1 = evt.x
                    y1 = evt.y
                    isScroll = false
                }
                MotionEvent.ACTION_MOVE -> {
                    // 通知其父控件不拦截
                    val x2 = evt.x
                    val y2 = evt.y
                    if (x1 - x2 > 1) {
                        //str = "向右滑"
                        parent.requestDisallowInterceptTouchEvent(true)
                        isScroll = false
                    } else if (x2 - x1 > 1) {
                        //str = "向左滑"
                        parent.requestDisallowInterceptTouchEvent(true)
                        isScroll = false
                    } else if (y1 - y2 > 100) {
                        parent.requestDisallowInterceptTouchEvent(false)
                        //str = "向上滑"
                        isScroll = true
                    } else if (y2 - y1 > 100) {
                        parent.requestDisallowInterceptTouchEvent(false)
                        //str = "向下滑"
                        isScroll = true
                    }
                }
                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                    if (isScroll) {
                        parent.requestDisallowInterceptTouchEvent(false)
                    } else {
                        parent.requestDisallowInterceptTouchEvent(true)
                    }
                }
            }
        }
        return super.dispatchTouchEvent(evt)
    }

}
复制代码

只需要换个集成的对象就行,一样的逻辑,如果对于阈值需要调整,可以使用上面的 scaledTouchSlop

webview卡顿

一般情况下webview不会卡顿,除非用法不但,或者确实由于网页导致的,如果是网页导致的只能本地化或者缓存或者预加载处理,但是如果是用法不但就需要自己找原因了

比如有时候代码写的烂,界面刷新频繁导致webview闪烁,就会关闭硬件加速 webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null),但是后来会发现滑动卡顿了,那肯定不能这么干

打开硬件加速,优化更新逻辑,问题解决

 

posted on   翻滚的咸鱼  阅读(935)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 【.NET】调用本地 Deepseek 模型
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示