CoordinatorLayout中AppBarLayout滑动抖动问题

CoordinatorLayout中AppBarLayout滑动抖动问题

问题描述

通过观察导致抖动的手势操作,知晓了在快速滑动AppBarLayout部分,手指离开屏幕,滑动还没有结束的时候,快速反向滑动View,就能够稳定复现抖动问题。

问题根源

两个点

  • 手指离开屏幕且滑动没有结束,说明了,此时正处于fling的过程。
  • 而滑动View时会产生抖动,说明了,fling这个过程仍然在进行,并没有因为新的滑动事件出现被取消。

通过翻阅源码AppBarLayout的fling由OverScroller执行,并且在事件机制中没有针对MotionEvent.ACTION_CANCEL的滑动停止操作。定位到问题后就好解决了,针对ACTION_CANCEL,获取scroller并将其终止。

解决方案

class CstAppbarLayout : AppBarLayout {

    constructor(context: Context) : super(context)
    constructor(context: Context, attr: AttributeSet?) : super(context, attr)
    constructor(context: Context, attr: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attr,
        defStyleAttr
    )

    override fun getBehavior(): CoordinatorLayout.Behavior {
        return object : AppBarLayout.BaseBehavior() {
            override fun onInterceptTouchEvent(
                parent: CoordinatorLayout,
                child: AppBarLayout,
                ev: MotionEvent
            ): Boolean {

                val result = super.onInterceptTouchEvent(parent, child, ev)

                if (ev.action == MotionEvent.ACTION_CANCEL && ev.x == 0f && ev.y == 0f && ev.metaState == 0) {

                    val scroller = this.javaClass.superclass?.superclass?.getDeclaredField("scroller")
                        ?.apply {
                            isAccessible = true
                        }?.get(this) as? OverScroller
                    // There is an animation in progress. Stop it.
                    if (scroller != null && !scroller.isFinished) {
                        scroller.abortAnimation()
                    }
                }

                return result
            }
        }
    }
}

你可能感兴趣的:(CoordinatorLayout中AppBarLayout滑动抖动问题)