Refactor helper method for ScrollView to not detect scroll direction
Summary: The helper class for ScrollView should not need to detect the scroll direction. If it has to do so, that means the corresponding logic should live in the `ReactScrollView` or `ReactHorizontalScrollView` respectively. This diff is to remove the scroll direction detection logic from the scroll view helper. Long term we should keep it this way as the shared code got moved to the helper class from the scroll view classes. Changelog: [Internal] Reviewed By: javache Differential Revision: D32514429 fbshipit-source-id: 2165f2eba90cc25d14834c39148fe8ce8805bea6
This commit is contained in:
Родитель
8ab2cbb78f
Коммит
508de3f351
|
@ -18,7 +18,6 @@ import android.animation.ValueAnimator;
|
|||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
@ -48,7 +47,6 @@ import com.facebook.react.uimanager.ViewProps;
|
|||
import com.facebook.react.uimanager.events.NativeGestureUtil;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasFlingAnimator;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasScrollState;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.ReactScrollViewScrollDirection;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.ReactScrollViewScrollState;
|
||||
import com.facebook.react.views.view.ReactViewBackgroundManager;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -141,8 +139,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|||
new ReactScrollViewScrollState(
|
||||
I18nUtil.getInstance().isRTL(context)
|
||||
? ViewCompat.LAYOUT_DIRECTION_RTL
|
||||
: ViewCompat.LAYOUT_DIRECTION_LTR,
|
||||
ReactScrollViewScrollDirection.HORIZONTAL);
|
||||
: ViewCompat.LAYOUT_DIRECTION_LTR);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -814,10 +811,13 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|||
// 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);
|
||||
Point postAnimationScroll = ReactScrollViewHelper.getPostAnimationScroll(this, velocityX > 0);
|
||||
scroller.fling(
|
||||
postAnimationScroll.x, // startX
|
||||
postAnimationScroll.y, // startY
|
||||
ReactScrollViewHelper.getNextFlingStartValue(
|
||||
this,
|
||||
getScrollX(),
|
||||
getReactScrollViewScrollState().getFinalAnimatedPositionScroll().x,
|
||||
velocityX > 0), // startX
|
||||
getScrollY(), // startY
|
||||
velocityX, // velocityX
|
||||
0, // velocityY
|
||||
0, // minX
|
||||
|
@ -842,7 +842,12 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
|||
|
||||
double interval = (double) getSnapInterval();
|
||||
double currentOffset =
|
||||
(double) (ReactScrollViewHelper.getPostAnimationScroll(this, velocity > 0).x);
|
||||
(double)
|
||||
(ReactScrollViewHelper.getNextFlingStartValue(
|
||||
this,
|
||||
getScrollX(),
|
||||
getReactScrollViewScrollState().getFinalAnimatedPositionScroll().x,
|
||||
velocity > 0));
|
||||
double targetOffset = (double) predictFinalScrollPosition(velocity);
|
||||
|
||||
int previousPage = (int) Math.floor(currentOffset / interval);
|
||||
|
|
|
@ -18,7 +18,6 @@ import android.animation.ValueAnimator;
|
|||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
@ -44,7 +43,6 @@ import com.facebook.react.uimanager.ViewProps;
|
|||
import com.facebook.react.uimanager.events.NativeGestureUtil;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasFlingAnimator;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.HasScrollState;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.ReactScrollViewScrollDirection;
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.ReactScrollViewScrollState;
|
||||
import com.facebook.react.views.view.ReactViewBackgroundManager;
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -102,8 +100,7 @@ public class ReactScrollView extends ScrollView
|
|||
private int pendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
private final FabricViewStateManager mFabricViewStateManager = new FabricViewStateManager();
|
||||
private final ReactScrollViewScrollState mReactScrollViewScrollState =
|
||||
new ReactScrollViewScrollState(
|
||||
ViewCompat.LAYOUT_DIRECTION_LTR, ReactScrollViewScrollDirection.VERTICAL);
|
||||
new ReactScrollViewScrollState(ViewCompat.LAYOUT_DIRECTION_LTR);
|
||||
private final ValueAnimator DEFAULT_FLING_ANIMATOR = ObjectAnimator.ofInt(this, "scrollY", 0, 0);
|
||||
|
||||
public ReactScrollView(Context context) {
|
||||
|
@ -603,10 +600,13 @@ public class ReactScrollView extends ScrollView
|
|||
// predict where a fling would end up so we can scroll to the nearest snap offset
|
||||
int maximumOffset = getMaxScrollY();
|
||||
int height = getHeight() - getPaddingBottom() - getPaddingTop();
|
||||
Point postAnimationScroll = ReactScrollViewHelper.getPostAnimationScroll(this, velocityY > 0);
|
||||
scroller.fling(
|
||||
postAnimationScroll.x, // startX
|
||||
postAnimationScroll.y, // startY
|
||||
getScrollX(), // startX
|
||||
ReactScrollViewHelper.getNextFlingStartValue(
|
||||
this,
|
||||
getScrollY(),
|
||||
getReactScrollViewScrollState().getFinalAnimatedPositionScroll().y,
|
||||
velocityY > 0), // startY
|
||||
0, // velocityX
|
||||
velocityY, // velocityY
|
||||
0, // minX
|
||||
|
@ -631,7 +631,12 @@ public class ReactScrollView extends ScrollView
|
|||
private void smoothScrollAndSnap(int velocity) {
|
||||
double interval = (double) getSnapInterval();
|
||||
double currentOffset =
|
||||
(double) (ReactScrollViewHelper.getPostAnimationScroll(this, velocity > 0).y);
|
||||
(double)
|
||||
(ReactScrollViewHelper.getNextFlingStartValue(
|
||||
this,
|
||||
getScrollY(),
|
||||
getReactScrollViewScrollState().getFinalAnimatedPositionScroll().y,
|
||||
velocity > 0));
|
||||
double targetOffset = (double) predictFinalScrollPosition(velocity);
|
||||
|
||||
int previousPage = (int) Math.floor(currentOffset / interval);
|
||||
|
|
|
@ -215,24 +215,16 @@ public class ReactScrollViewHelper {
|
|||
sScrollListeners.remove(listener);
|
||||
}
|
||||
|
||||
public enum ReactScrollViewScrollDirection {
|
||||
HORIZONTAL,
|
||||
VERTICAL,
|
||||
}
|
||||
|
||||
public static class ReactScrollViewScrollState {
|
||||
private final int mLayoutDirection;
|
||||
private final ReactScrollViewScrollDirection mScrollDirection;
|
||||
private final Point mFinalAnimatedPositionScroll = new Point();
|
||||
private int mScrollAwayPaddingTop = 0;
|
||||
private final Point mLastStateUpdateScroll = new Point(-1, -1);
|
||||
private boolean mIsCanceled = false;
|
||||
private boolean mIsFinished = true;
|
||||
|
||||
public ReactScrollViewScrollState(
|
||||
final int layoutDirection, final ReactScrollViewScrollDirection scrollDirection) {
|
||||
public ReactScrollViewScrollState(final int layoutDirection) {
|
||||
mLayoutDirection = layoutDirection;
|
||||
mScrollDirection = scrollDirection;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -243,14 +235,6 @@ public class ReactScrollViewHelper {
|
|||
return mLayoutDirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the scroll direction. Can be either ReactScrollViewScrollDirection.HORIZONTAL or
|
||||
* ReactScrollViewScrollDirection.VERTICAL.
|
||||
*/
|
||||
public ReactScrollViewScrollDirection getScrollDirection() {
|
||||
return mScrollDirection;
|
||||
}
|
||||
|
||||
/** Get the position after current animation is finished */
|
||||
public Point getFinalAnimatedPositionScroll() {
|
||||
return mFinalAnimatedPositionScroll;
|
||||
|
@ -334,43 +318,32 @@ public class ReactScrollViewHelper {
|
|||
|
||||
final int scrollX = scrollView.getScrollX();
|
||||
final int scrollY = scrollView.getScrollY();
|
||||
final ReactScrollViewScrollDirection scrollDirection = scrollState.getScrollDirection();
|
||||
if (scrollDirection == ReactScrollViewScrollDirection.HORIZONTAL && scrollX != x) {
|
||||
// Only one fling animator will be started. For the horizontal scroll view, scrollY will always
|
||||
// be the same to y. This is the same to the vertical scroll view.
|
||||
if (scrollX != x) {
|
||||
scrollView.startFlingAnimator(scrollX, x);
|
||||
}
|
||||
if (scrollDirection == ReactScrollViewScrollDirection.VERTICAL && scrollY != y) {
|
||||
if (scrollY != y) {
|
||||
scrollView.startFlingAnimator(scrollY, y);
|
||||
}
|
||||
|
||||
updateFabricScrollState(scrollView, x, y);
|
||||
}
|
||||
|
||||
/** Get current (x, y) position or position after current animation finishes, if any. */
|
||||
/** Get current position or position after current animation finishes, if any. */
|
||||
public static <
|
||||
T extends
|
||||
ViewGroup & FabricViewStateManager.HasFabricViewStateManager & HasScrollState
|
||||
& HasFlingAnimator>
|
||||
Point getPostAnimationScroll(final T scrollView, final boolean isPositiveVelocity) {
|
||||
int getNextFlingStartValue(
|
||||
final T scrollView,
|
||||
final int currentValue,
|
||||
final int postAnimationValue,
|
||||
final boolean isPositiveVelocity) {
|
||||
final ReactScrollViewScrollState scrollState = scrollView.getReactScrollViewScrollState();
|
||||
final int velocityDirectionMask = isPositiveVelocity ? 1 : -1;
|
||||
final Point animatedScrollPos = scrollState.getFinalAnimatedPositionScroll();
|
||||
final Point currentScrollPos = new Point(scrollView.getScrollX(), scrollView.getScrollY());
|
||||
|
||||
boolean isMovingTowardsAnimatedValue = false;
|
||||
switch (scrollState.getScrollDirection()) {
|
||||
case HORIZONTAL:
|
||||
isMovingTowardsAnimatedValue =
|
||||
velocityDirectionMask * (animatedScrollPos.x - currentScrollPos.x) > 0;
|
||||
break;
|
||||
|
||||
case VERTICAL:
|
||||
isMovingTowardsAnimatedValue =
|
||||
velocityDirectionMask * (animatedScrollPos.y - currentScrollPos.y) > 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new IllegalArgumentException("ScrollView has unexpected scroll direction.");
|
||||
}
|
||||
final boolean isMovingTowardsAnimatedValue =
|
||||
velocityDirectionMask * (postAnimationValue - currentValue) > 0;
|
||||
|
||||
// When the fling animation is not finished, or it was canceled and now we are moving towards
|
||||
// the final animated value, we will return the final animated value. This is because follow up
|
||||
|
@ -378,8 +351,8 @@ public class ReactScrollViewHelper {
|
|||
// scrolls are still working.
|
||||
return !scrollState.getIsFinished()
|
||||
|| (scrollState.getIsCanceled() && isMovingTowardsAnimatedValue)
|
||||
? animatedScrollPos
|
||||
: currentScrollPos;
|
||||
? postAnimationValue
|
||||
: currentValue;
|
||||
}
|
||||
|
||||
public static <
|
||||
|
|
Загрузка…
Ссылка в новой задаче