CoordinatorLayout中AppBarLayout滑动
2021-01-08 本文已影响0人
Raven
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
}
}
}
}