mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Refactor predictFinalScrollPosition method to the helper class
Summary: This diff refactors method `predictFinalScrollPosition` in `ReactScrollView` and `ReactHorizontalScrollView` to the helper class. This will make future changes to the prediction logic easier. Changelog: [Internal] Reviewed By: javache Differential Revision: D32571735 fbshipit-source-id: 7e7e21ac51f929a017cd43de094ed39478fe4032
This commit is contained in:
committed by
Facebook GitHub Bot
parent
1c1945569f
commit
66243271a7
+4
-28
@@ -93,7 +93,6 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
private int mEndFillColor = Color.TRANSPARENT;
|
||||
private boolean mDisableIntervalMomentum = false;
|
||||
private int mSnapInterval = 0;
|
||||
private float mDecelerationRate = 0.985f;
|
||||
private @Nullable List<Integer> mSnapOffsets;
|
||||
private boolean mSnapToStart = true;
|
||||
private boolean mSnapToEnd = true;
|
||||
@@ -216,10 +215,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
}
|
||||
|
||||
public void setDecelerationRate(float decelerationRate) {
|
||||
mDecelerationRate = decelerationRate;
|
||||
getReactScrollViewScrollState().setDecelerationRate(decelerationRate);
|
||||
|
||||
if (mScroller != null) {
|
||||
mScroller.setFriction(1.0f - mDecelerationRate);
|
||||
mScroller.setFriction(1.0f - decelerationRate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -802,32 +801,9 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
}
|
||||
|
||||
private int predictFinalScrollPosition(int velocityX) {
|
||||
// ScrollView can *only* scroll for 250ms when using smoothScrollTo and there's
|
||||
// no way to customize the scroll duration. So, we create a temporary OverScroller
|
||||
// so we can predict where a fling would land and snap to nearby that point.
|
||||
OverScroller scroller = new OverScroller(getContext());
|
||||
scroller.setFriction(1.0f - mDecelerationRate);
|
||||
|
||||
// predict where a fling would end up so we can scroll to the nearest snap offset
|
||||
int maximumOffset = Math.max(0, computeHorizontalScrollRange() - getWidth());
|
||||
int width = getWidth() - ViewCompat.getPaddingStart(this) - ViewCompat.getPaddingEnd(this);
|
||||
scroller.fling(
|
||||
ReactScrollViewHelper.getNextFlingStartValue(
|
||||
this,
|
||||
getScrollX(),
|
||||
getReactScrollViewScrollState().getFinalAnimatedPositionScroll().x,
|
||||
velocityX), // startX
|
||||
getScrollY(), // startY
|
||||
velocityX, // velocityX
|
||||
0, // velocityY
|
||||
0, // minX
|
||||
maximumOffset, // maxX
|
||||
0, // minY
|
||||
0, // maxY
|
||||
width / 2, // overX
|
||||
0 // overY
|
||||
);
|
||||
return scroller.getFinalX();
|
||||
final int maximumOffset = Math.max(0, computeHorizontalScrollRange() - getWidth());
|
||||
return ReactScrollViewHelper.predictFinalScrollPosition(this, velocityX, 0, maximumOffset, 0).x;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,7 +89,6 @@ public class ReactScrollView extends ScrollView
|
||||
private int mEndFillColor = Color.TRANSPARENT;
|
||||
private boolean mDisableIntervalMomentum = false;
|
||||
private int mSnapInterval = 0;
|
||||
private float mDecelerationRate = 0.985f;
|
||||
private @Nullable List<Integer> mSnapOffsets;
|
||||
private boolean mSnapToStart = true;
|
||||
private boolean mSnapToEnd = true;
|
||||
@@ -191,10 +190,10 @@ public class ReactScrollView extends ScrollView
|
||||
}
|
||||
|
||||
public void setDecelerationRate(float decelerationRate) {
|
||||
mDecelerationRate = decelerationRate;
|
||||
getReactScrollViewScrollState().setDecelerationRate(decelerationRate);
|
||||
|
||||
if (mScroller != null) {
|
||||
mScroller.setFriction(1.0f - mDecelerationRate);
|
||||
mScroller.setFriction(1.0f - decelerationRate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,32 +590,9 @@ public class ReactScrollView extends ScrollView
|
||||
}
|
||||
|
||||
private int predictFinalScrollPosition(int velocityY) {
|
||||
// ScrollView can *only* scroll for 250ms when using smoothScrollTo and there's
|
||||
// no way to customize the scroll duration. So, we create a temporary OverScroller
|
||||
// so we can predict where a fling would land and snap to nearby that point.
|
||||
OverScroller scroller = new OverScroller(getContext());
|
||||
scroller.setFriction(1.0f - mDecelerationRate);
|
||||
|
||||
// predict where a fling would end up so we can scroll to the nearest snap offset
|
||||
int maximumOffset = getMaxScrollY();
|
||||
int height = getHeight() - getPaddingBottom() - getPaddingTop();
|
||||
scroller.fling(
|
||||
getScrollX(), // startX
|
||||
ReactScrollViewHelper.getNextFlingStartValue(
|
||||
this,
|
||||
getScrollY(),
|
||||
getReactScrollViewScrollState().getFinalAnimatedPositionScroll().y,
|
||||
velocityY), // startY
|
||||
0, // velocityX
|
||||
velocityY, // velocityY
|
||||
0, // minX
|
||||
0, // maxX
|
||||
0, // minY
|
||||
maximumOffset, // maxY
|
||||
0, // overX
|
||||
height / 2 // overY
|
||||
);
|
||||
return scroller.getFinalY();
|
||||
return ReactScrollViewHelper.predictFinalScrollPosition(this, 0, velocityY, 0, getMaxScrollY())
|
||||
.y;
|
||||
}
|
||||
|
||||
private View getContentView() {
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.OverScroller;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
@@ -222,6 +223,7 @@ public class ReactScrollViewHelper {
|
||||
private final Point mLastStateUpdateScroll = new Point(-1, -1);
|
||||
private boolean mIsCanceled = false;
|
||||
private boolean mIsFinished = true;
|
||||
private float mDecelerationRate = 0.985f;
|
||||
|
||||
public ReactScrollViewScrollState(final int layoutDirection) {
|
||||
mLayoutDirection = layoutDirection;
|
||||
@@ -291,6 +293,17 @@ public class ReactScrollViewHelper {
|
||||
mIsFinished = isFinished;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Get true if previous animation was finished */
|
||||
public float getDecelerationRate() {
|
||||
return mDecelerationRate;
|
||||
}
|
||||
|
||||
/** Set the state of current animation is finished or not */
|
||||
public ReactScrollViewScrollState setDecelerationRate(float decelerationRate) {
|
||||
mDecelerationRate = decelerationRate;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -491,6 +504,54 @@ public class ReactScrollViewHelper {
|
||||
});
|
||||
}
|
||||
|
||||
public static <
|
||||
T extends
|
||||
ViewGroup & FabricViewStateManager.HasFabricViewStateManager & HasScrollState
|
||||
& HasFlingAnimator>
|
||||
Point predictFinalScrollPosition(
|
||||
final T scrollView,
|
||||
int velocityX,
|
||||
int velocityY,
|
||||
int maximumOffsetX,
|
||||
int maximumOffsetY) {
|
||||
final ReactScrollViewScrollState scrollState = scrollView.getReactScrollViewScrollState();
|
||||
// ScrollView can *only* scroll for 250ms when using smoothScrollTo and there's
|
||||
// no way to customize the scroll duration. So, we create a temporary OverScroller
|
||||
// so we can predict where a fling would land and snap to nearby that point.
|
||||
OverScroller scroller = new OverScroller(scrollView.getContext());
|
||||
scroller.setFriction(1.0f - scrollState.getDecelerationRate());
|
||||
|
||||
// predict where a fling would end up so we can scroll to the nearest snap offset
|
||||
int width =
|
||||
scrollView.getWidth()
|
||||
- ViewCompat.getPaddingStart(scrollView)
|
||||
- ViewCompat.getPaddingEnd(scrollView);
|
||||
int height =
|
||||
scrollView.getHeight() - scrollView.getPaddingBottom() - scrollView.getPaddingTop();
|
||||
Point finalAnimatedPositionScroll = scrollState.getFinalAnimatedPositionScroll();
|
||||
scroller.fling(
|
||||
getNextFlingStartValue(
|
||||
scrollView,
|
||||
scrollView.getScrollX(),
|
||||
finalAnimatedPositionScroll.x,
|
||||
velocityX), // startX
|
||||
getNextFlingStartValue(
|
||||
scrollView,
|
||||
scrollView.getScrollY(),
|
||||
finalAnimatedPositionScroll.y,
|
||||
velocityY), // startY
|
||||
velocityX, // velocityX
|
||||
velocityY, // velocityY
|
||||
0, // minX
|
||||
maximumOffsetX, // maxX
|
||||
0, // minY
|
||||
maximumOffsetY, // maxY
|
||||
width / 2, // overX
|
||||
height / 2 // overY
|
||||
);
|
||||
return new Point(scroller.getFinalX(), scroller.getFinalY());
|
||||
}
|
||||
|
||||
public interface HasScrollState {
|
||||
/** Get the scroll state for the current ScrollView */
|
||||
ReactScrollViewScrollState getReactScrollViewScrollState();
|
||||
|
||||
Reference in New Issue
Block a user