NekoX/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearSmoothScrollerCustom....

159 lines
5.5 KiB
Java

/*
* This is the source code of Telegram for Android v. 5.x.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2018.
*/
package androidx.recyclerview.widget;
import android.content.Context;
import android.graphics.PointF;
import androidx.annotation.Nullable;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import org.telegram.messenger.AndroidUtilities;
public class LinearSmoothScrollerCustom extends RecyclerView.SmoothScroller {
private static final float MILLISECONDS_PER_INCH = 25f;
private static final int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000;
private static final float TARGET_SEEK_EXTRA_SCROLL_RATIO = 1.2f;
protected final LinearInterpolator mLinearInterpolator = new LinearInterpolator();
protected final DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator(1.5f);
protected PointF mTargetVector;
private final float MILLISECONDS_PER_PX;
protected int mInterimTargetDx = 0, mInterimTargetDy = 0;
private int scrollPosition;
public static final int POSITION_MIDDLE = 0;
public static final int POSITION_END = 1;
public static final int POSITION_TOP = 2;
public LinearSmoothScrollerCustom(Context context, int position) {
MILLISECONDS_PER_PX = MILLISECONDS_PER_INCH / context.getResources().getDisplayMetrics().densityDpi;
scrollPosition = position;
}
@Override
protected void onStart() {
}
@Override
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
final int dy = calculateDyToMakeVisible(targetView);
final int time = calculateTimeForDeceleration(dy);
if (time > 0) {
action.update(0, -dy, Math.max(400, time), mDecelerateInterpolator);
}
}
@Override
protected void onSeekTargetStep(int dx, int dy, RecyclerView.State state, Action action) {
if (getChildCount() == 0) {
stop();
return;
}
mInterimTargetDx = clampApplyScroll(mInterimTargetDx, dx);
mInterimTargetDy = clampApplyScroll(mInterimTargetDy, dy);
if (mInterimTargetDx == 0 && mInterimTargetDy == 0) {
updateActionForInterimTarget(action);
}
}
@Override
protected void onStop() {
mInterimTargetDx = mInterimTargetDy = 0;
mTargetVector = null;
}
protected int calculateTimeForDeceleration(int dx) {
return (int) Math.ceil(calculateTimeForScrolling(dx) / .3356);
}
protected int calculateTimeForScrolling(int dx) {
return (int) Math.ceil(Math.abs(dx) * MILLISECONDS_PER_PX);
}
protected void updateActionForInterimTarget(Action action) {
PointF scrollVector = computeScrollVectorForPosition(getTargetPosition());
if (scrollVector == null || (scrollVector.x == 0 && scrollVector.y == 0)) {
final int target = getTargetPosition();
action.jumpTo(target);
stop();
return;
}
normalize(scrollVector);
mTargetVector = scrollVector;
mInterimTargetDx = (int) (TARGET_SEEK_SCROLL_DISTANCE_PX * scrollVector.x);
mInterimTargetDy = (int) (TARGET_SEEK_SCROLL_DISTANCE_PX * scrollVector.y);
final int time = calculateTimeForScrolling(TARGET_SEEK_SCROLL_DISTANCE_PX);
action.update((int) (mInterimTargetDx * TARGET_SEEK_EXTRA_SCROLL_RATIO), (int) (mInterimTargetDy * TARGET_SEEK_EXTRA_SCROLL_RATIO), (int) (time * TARGET_SEEK_EXTRA_SCROLL_RATIO), mLinearInterpolator);
}
private int clampApplyScroll(int tmpDt, int dt) {
final int before = tmpDt;
tmpDt -= dt;
if (before * tmpDt <= 0) {
return 0;
}
return tmpDt;
}
public int calculateDyToMakeVisible(View view) {
final RecyclerView.LayoutManager layoutManager = getLayoutManager();
if (layoutManager == null || !layoutManager.canScrollVertically()) {
return 0;
}
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
int top = layoutManager.getDecoratedTop(view) - params.topMargin;
int bottom = layoutManager.getDecoratedBottom(view) + params.bottomMargin;
int start = layoutManager.getPaddingTop();
int end = layoutManager.getHeight() - layoutManager.getPaddingBottom();
int boxSize = end - start;
int viewSize = bottom - top;
if (scrollPosition == POSITION_TOP) {
start = layoutManager.getPaddingTop();
} else if (viewSize > boxSize) {
start = 0;
} else if (scrollPosition == POSITION_MIDDLE) {
start = (boxSize - viewSize) / 2;
} else {
start = (layoutManager.getPaddingTop() - AndroidUtilities.dp(88));
}
end = start + viewSize;
final int dtStart = start - top;
if (dtStart > 0) {
return dtStart;
}
final int dtEnd = end - bottom;
if (dtEnd < 0) {
return dtEnd;
}
return 0;
}
@Nullable
public PointF computeScrollVectorForPosition(int targetPosition) {
RecyclerView.LayoutManager layoutManager = getLayoutManager();
if (layoutManager instanceof ScrollVectorProvider) {
return ((ScrollVectorProvider) layoutManager).computeScrollVectorForPosition(targetPosition);
}
return null;
}
}