Created
August 9, 2017 07:14
-
-
Save JSpiner/69c203b13629927d7d13c8987969f78e to your computer and use it in GitHub Desktop.
Smooth Scroll AppBarLayout FlingBehavior
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public final class FlingBehavior extends AppBarLayout.Behavior { | |
private boolean isPositive; | |
private float mFlingFriction = ViewConfiguration.getScrollFriction(); | |
private float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9)); | |
private final float INFLEXION = 0.35f; | |
private float mPhysicalCoeff; | |
//https://stackoverflow.com/questions/30923889/flinging-with-recyclerview-appbarlayout | |
//I made java version by referring to julian's kotlin code and subtract reflection. | |
//https://stackoverflow.com/a/43594597/7957535 | |
public FlingBehavior(){ | |
init(); | |
} | |
public FlingBehavior(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
init(); | |
} | |
private void init(){ | |
final float ppi = BaseApplication.getInstance().getResources().getDisplayMetrics().density * 160.0f; | |
mPhysicalCoeff = SensorManager.GRAVITY_EARTH // g (m/s^2) | |
* 39.37f // inch/meter | |
* ppi | |
* 0.84f; // look and feel tuning | |
} | |
@Override | |
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) { | |
if (velocityY > 0 && !isPositive || velocityY < 0 && isPositive) { | |
velocityY = velocityY * -1; | |
} | |
if (target instanceof RecyclerView && velocityY < 0) { | |
RecyclerView recyclerView = (RecyclerView) target; | |
double distance = getFlingDistance((int) velocityY); | |
if (distance < recyclerView.computeVerticalScrollOffset()) { | |
consumed = true; | |
} else { | |
consumed = false; | |
} | |
} | |
return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); | |
} | |
@Override | |
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed) { | |
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); | |
isPositive = dy > 0; | |
} | |
public double getFlingDistance(int velocity){ | |
final double l = getSplineDeceleration(velocity); | |
final double decelMinusOne = DECELERATION_RATE - 1.0; | |
return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l); | |
} | |
private double getSplineDeceleration(int velocity) { | |
return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment