滑动冲突

有时候 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),但是后来会发现滑动卡顿了,那肯定不能这么干

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