mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13:00 +00:00 
			
		
		
		
	fix scroll jittering
This commit is contained in:
		| @@ -1,116 +1,80 @@ | ||||
| package android.support.design.widget; | ||||
|  | ||||
| import android.animation.ValueAnimator; | ||||
| import android.content.Context; | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.design.animation.AnimationUtils; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.util.AttributeSet; | ||||
| import android.view.View; | ||||
| import android.view.MotionEvent; | ||||
| import android.widget.OverScroller; | ||||
|  | ||||
| // check this https://github.com/ToDou/appbarlayout-spring-behavior/blob/master/appbarspring/src/main/java/android/support/design/widget/AppBarFlingFixBehavior.java | ||||
| import java.lang.reflect.Field; | ||||
|  | ||||
| // check this https://stackoverflow.com/questions/56849221/recyclerview-fling-causes-laggy-while-appbarlayout-is-scrolling/57997489#57997489 | ||||
| public final class FlingBehavior extends AppBarLayout.Behavior { | ||||
|  | ||||
|     private ValueAnimator mOffsetAnimator; | ||||
|     private static final int MAX_OFFSET_ANIMATION_DURATION = 600; // ms | ||||
|  | ||||
|     public FlingBehavior() { | ||||
|     } | ||||
|  | ||||
|     public FlingBehavior(Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) { | ||||
|         if (dy != 0) { | ||||
|             int val = child.getBottom(); | ||||
|             if (val != 0) { | ||||
|                 int min, max; | ||||
|                 if (dy < 0) { | ||||
|                     // We're scrolling down | ||||
|                 } else { | ||||
|                     // We're scrolling up | ||||
|                     if (mOffsetAnimator != null && mOffsetAnimator.isRunning()) { | ||||
|                         mOffsetAnimator.cancel(); | ||||
|     public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) { | ||||
|         switch (ev.getActionMasked()) { | ||||
|             case MotionEvent.ACTION_DOWN: | ||||
|                 // remove reference to old nested scrolling child | ||||
|                 resetNestedScrollingChild(); | ||||
|                 // Stop fling when your finger touches the screen | ||||
|                 stopAppBarLayoutFling(); | ||||
|                 break; | ||||
|             default: | ||||
|                 break; | ||||
|         } | ||||
|                     min = -child.getUpNestedPreScrollRange(); | ||||
|                     max = 0; | ||||
|                     consumed[1] = scroll(coordinatorLayout, child, dy, min, max); | ||||
|         return super.onInterceptTouchEvent(parent, child, ev); | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     private OverScroller getScrollerField() { | ||||
|         try { | ||||
|             Class<?> headerBehaviorType = this.getClass().getSuperclass().getSuperclass().getSuperclass(); | ||||
|             if (headerBehaviorType != null) { | ||||
|                 Field field = headerBehaviorType.getDeclaredField("scroller"); | ||||
|                 field.setAccessible(true); | ||||
|                 return ((OverScroller) field.get(this)); | ||||
|             } | ||||
|         } catch (NoSuchFieldException | IllegalAccessException e) { | ||||
|             // ? | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     private Field getLastNestedScrollingChildRefField() { | ||||
|         try { | ||||
|             Class<?> headerBehaviorType = this.getClass().getSuperclass().getSuperclass(); | ||||
|             if (headerBehaviorType != null) { | ||||
|                 Field field = headerBehaviorType.getDeclaredField("lastNestedScrollingChildRef"); | ||||
|                 field.setAccessible(true); | ||||
|                 return field; | ||||
|             } | ||||
|         } catch (NoSuchFieldException e) { | ||||
|             // ? | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     private void resetNestedScrollingChild(){ | ||||
|         Field field = getLastNestedScrollingChildRefField(); | ||||
|         if(field != null){ | ||||
|             try { | ||||
|                 Object value = field.get(this); | ||||
|                 if(value != null) field.set(this, null); | ||||
|             } catch (IllegalAccessException e) { | ||||
|                 // ? | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean onNestedPreFling(@NonNull CoordinatorLayout coordinatorLayout, @NonNull AppBarLayout child, @NonNull View target, float velocityX, float velocityY) { | ||||
|  | ||||
|         if (velocityY != 0) { | ||||
|             if (velocityY < 0) { | ||||
|                 // We're flinging down | ||||
|                 int val = child.getBottom(); | ||||
|                 if (val != 0) { | ||||
|                     final int targetScroll = | ||||
|                             +child.getDownNestedPreScrollRange(); | ||||
|                     animateOffsetTo(coordinatorLayout, child, targetScroll, velocityY); | ||||
|     private void stopAppBarLayoutFling() { | ||||
|         OverScroller scroller = getScrollerField(); | ||||
|         if (scroller != null) scroller.forceFinished(true); | ||||
|     } | ||||
|  | ||||
|             } else { | ||||
|                 // We're flinging up | ||||
|                 int val = child.getBottom(); | ||||
|                 if (val != 0) { | ||||
|                     final int targetScroll = -child.getUpNestedPreScrollRange(); | ||||
|                     if (getTopBottomOffsetForScrollingSibling() > targetScroll) { | ||||
|                         animateOffsetTo(coordinatorLayout, child, targetScroll, velocityY); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY); | ||||
|     } | ||||
|  | ||||
|     private void animateOffsetTo(final CoordinatorLayout coordinatorLayout, | ||||
|                                  final AppBarLayout child, final int offset, float velocity) { | ||||
|         final int distance = Math.abs(getTopBottomOffsetForScrollingSibling() - offset); | ||||
|  | ||||
|         final int duration; | ||||
|         velocity = Math.abs(velocity); | ||||
|         if (velocity > 0) { | ||||
|             duration = 3 * Math.round(1000 * (distance / velocity)); | ||||
|         } else { | ||||
|             final float distanceRatio = (float) distance / child.getHeight(); | ||||
|             duration = (int) ((distanceRatio + 1) * 150); | ||||
|         } | ||||
|  | ||||
|         animateOffsetWithDuration(coordinatorLayout, child, offset, duration); | ||||
|     } | ||||
|  | ||||
|     private void animateOffsetWithDuration(final CoordinatorLayout coordinatorLayout, | ||||
|                                            final AppBarLayout child, final int offset, final int duration) { | ||||
|         final int currentOffset = getTopBottomOffsetForScrollingSibling(); | ||||
|         if (currentOffset == offset) { | ||||
|             if (mOffsetAnimator != null && mOffsetAnimator.isRunning()) { | ||||
|                 mOffsetAnimator.cancel(); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (mOffsetAnimator == null) { | ||||
|             mOffsetAnimator = new ValueAnimator(); | ||||
|             mOffsetAnimator.setInterpolator(AnimationUtils.DECELERATE_INTERPOLATOR); | ||||
|             mOffsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { | ||||
|                 @Override | ||||
|                 public void onAnimationUpdate(ValueAnimator animator) { | ||||
|                     setHeaderTopBottomOffset(coordinatorLayout, child, | ||||
|                             (Integer) animator.getAnimatedValue()); | ||||
|                 } | ||||
|             }); | ||||
|         } else { | ||||
|             mOffsetAnimator.cancel(); | ||||
|         } | ||||
|  | ||||
|         mOffsetAnimator.setDuration(Math.min(duration, MAX_OFFSET_ANIMATION_DURATION)); | ||||
|         mOffsetAnimator.setIntValues(currentOffset, offset); | ||||
|         mOffsetAnimator.start(); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 yausername
					yausername