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<AppBarLayout> {
        return object : AppBarLayout.BaseBehavior<AppBarLayout>() {
            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
            }
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容