FixAppBarLayoutBehavior的小小改进
2021-01-29 本文已影响0人
颤抖的闪电
关于CoordinatorLayout和AppBarLayout 嵌套滑动时抖动的一个原生bug网上有很多文章,我就不细说了,可以看一下这个CoordinatorLayout和AppBarLayout 嵌套滑动时抖动的一个原生bug,里面涉及到的FixAppBarLayoutBehavior这个类,关于反射拿到OverScroller对象实体的地方,需要小小改进一下,如下,此处就做一个小小的记录吧。
package com.msyc.onion.ui.commons.behavior;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.OverScroller;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.view.ViewCompat;
import com.google.android.material.appbar.AppBarLayout;
import java.lang.reflect.Field;
import static android.view.MotionEvent.ACTION_DOWN;
/**
* Workaround AppBarLayout.Behavior for https://issuetracker.google.com/66996774
* <p>
* See https://gist.github.com/chrisbanes/8391b5adb9ee42180893300850ed02f2 for
* example usage.
* <p>
* Change the package name as you wish.
*/
public class FixAppBarLayoutBehavior extends AppBarLayout.Behavior {
private static final String TAG = "AppBarLayoutBehavior";
public FixAppBarLayoutBehavior() {
super();
}
public FixAppBarLayoutBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
if (ev.getAction() == ACTION_DOWN) {
Object scroller = getSuperSuperField(this);
if (scroller != null && scroller instanceof OverScroller) {
OverScroller overScroller = (OverScroller) scroller;
overScroller.abortAnimation();
}
}
return super.onInterceptTouchEvent(parent, child, ev);
}
private Object getSuperSuperField(Object paramClass) {
Field field;
Object object = null;
try {
Class cla = (Class) paramClass.getClass().getSuperclass().getSuperclass().getSuperclass();
field = cla.getDeclaredField("scroller");
field.setAccessible(true);
System.out.println("单个对象的某个键的值==反射==" + field.get(paramClass));
object = field.get(paramClass);
if (object == null) {
field = paramClass.getClass().getSuperclass().getSuperclass().getDeclaredField("mScroller");
field.setAccessible(true);
object = field.get(paramClass);
}
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target,
int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type, int[] consume) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed,
dxUnconsumed, dyUnconsumed, type, consume);
stopNestedScrollIfNeeded(dyUnconsumed, child, target, type);
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child,
View target, int dx, int dy, int[] consumed, int type) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
stopNestedScrollIfNeeded(dy, child, target, type);
}
private void stopNestedScrollIfNeeded(int dy, AppBarLayout child, View target, int type) {
if (type == ViewCompat.TYPE_NON_TOUCH) {
final int currOffset = getTopAndBottomOffset();
if ((dy < 0 && currOffset == 0)
|| (dy > 0 && currOffset == -child.getTotalScrollRange())) {
ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH);
}
}
}
}