mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix HorizontalScrollView not reporting its contentOffset
Summary: # Problem HorizontalScrollView was not reporting its `contentOffset` to Fabric, therefore `measure` was returning wrong value. # Solution Copy over implementation of `updateState` from scrollView. I noticed that there is a lot of duplication between the two classes, that's why I decided to duplicate `updateState` as well. Changelog: [Internal] Reviewed By: JoshuaGross, mdvacca Differential Revision: D20247552 fbshipit-source-id: 48b1eb0c11198a32531effe55301f8d554e92130
This commit is contained in:
committed by
Facebook Github Bot
parent
d892bb889b
commit
4f908a569a
+56
-4
@@ -24,11 +24,15 @@ import androidx.core.text.TextUtilsCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.react.uimanager.MeasureSpecAssertions;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroup;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
|
||||
import com.facebook.react.uimanager.StateWrapper;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.events.NativeGestureUtil;
|
||||
import com.facebook.react.views.view.ReactViewBackgroundManager;
|
||||
@@ -43,6 +47,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
|
||||
private static @Nullable Field sScrollerField;
|
||||
private static boolean sTriedToGetScrollerField = false;
|
||||
private static final String CONTENT_OFFSET_LEFT = "contentOffsetLeft";
|
||||
private static final String CONTENT_OFFSET_TOP = "contentOffsetTop";
|
||||
|
||||
private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper();
|
||||
private final @Nullable OverScroller mScroller;
|
||||
@@ -70,6 +76,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
private boolean mSnapToEnd = true;
|
||||
private ReactViewBackgroundManager mReactBackgroundManager;
|
||||
private boolean mPagedArrowScrolling = false;
|
||||
private @Nullable StateWrapper mStateWrapper;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
@@ -217,7 +224,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
// Call with the present values in order to re-layout if necessary
|
||||
scrollTo(getScrollX(), getScrollY());
|
||||
reactScrollTo(getScrollX(), getScrollY());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,6 +390,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
mVelocityHelper.calculateVelocity(ev);
|
||||
int action = ev.getAction() & MotionEvent.ACTION_MASK;
|
||||
if (action == MotionEvent.ACTION_UP && mDragging) {
|
||||
updateStateOnScroll(getScrollX(), getScrollY());
|
||||
|
||||
float velocityX = mVelocityHelper.getXVelocity();
|
||||
float velocityY = mVelocityHelper.getYVelocity();
|
||||
ReactScrollViewHelper.emitScrollEndDragEvent(this, velocityX, velocityY);
|
||||
@@ -605,6 +614,8 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
ViewCompat.postOnAnimationDelayed(
|
||||
ReactHorizontalScrollView.this, this, ReactScrollViewHelper.MOMENTUM_DELAY);
|
||||
} else {
|
||||
updateStateOnScroll(getScrollX(), getScrollY());
|
||||
|
||||
if (mPagingEnabled && !mSnappingToPage) {
|
||||
// Only if we have pagingEnabled and we have not snapped to the page do we
|
||||
// need to continue checking for the scroll. And we cause that scroll by asking for
|
||||
@@ -698,7 +709,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
targetOffset = currentPage * interval;
|
||||
if (targetOffset != currentOffset) {
|
||||
mActivelyScrolling = true;
|
||||
smoothScrollTo((int) targetOffset, getScrollY());
|
||||
reactSmoothScrollTo((int) targetOffset, getScrollY());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,7 +845,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
|
||||
postInvalidateOnAnimation();
|
||||
} else {
|
||||
smoothScrollTo(targetOffset, getScrollY());
|
||||
reactSmoothScrollTo(targetOffset, getScrollY());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -857,7 +868,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
page = 0;
|
||||
}
|
||||
|
||||
smoothScrollTo(page * width, getScrollY());
|
||||
reactSmoothScrollTo(page * width, getScrollY());
|
||||
handlePostTouchScrolling(0, 0);
|
||||
}
|
||||
|
||||
@@ -885,4 +896,45 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
public void setBorderStyle(@Nullable String style) {
|
||||
mReactBackgroundManager.setBorderStyle(style);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls `smoothScrollTo` and updates state.
|
||||
*
|
||||
* <p>`smoothScrollTo` changes `contentOffset` and we need to keep `contentOffset` in sync between
|
||||
* scroll view and state. Calling raw `smoothScrollTo` doesn't update state.
|
||||
*/
|
||||
public void reactSmoothScrollTo(int x, int y) {
|
||||
smoothScrollTo(x, y);
|
||||
updateStateOnScroll(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls `reactScrollTo` and updates state.
|
||||
*
|
||||
* <p>`reactScrollTo` changes `contentOffset` and we need to keep `contentOffset` in sync between
|
||||
* scroll view and state. Calling raw `reactScrollTo` doesn't update state.
|
||||
*/
|
||||
public void reactScrollTo(int x, int y) {
|
||||
scrollTo(x, y);
|
||||
updateStateOnScroll(x, y);
|
||||
}
|
||||
|
||||
public void updateState(@Nullable StateWrapper stateWrapper) {
|
||||
mStateWrapper = stateWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on any stabilized onScroll change to propagate content offset value to a Shadow Node.
|
||||
*/
|
||||
private void updateStateOnScroll(int scrollX, int scrollY) {
|
||||
if (mStateWrapper == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
WritableMap map = new WritableNativeMap();
|
||||
map.putDouble(CONTENT_OFFSET_LEFT, PixelUtil.toDIPFromPixel(scrollX));
|
||||
map.putDouble(CONTENT_OFFSET_TOP, PixelUtil.toDIPFromPixel(scrollY));
|
||||
|
||||
mStateWrapper.updateState(map);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-4
@@ -16,7 +16,9 @@ import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
import com.facebook.react.uimanager.StateWrapper;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
@@ -62,6 +64,15 @@ public class ReactHorizontalScrollViewManager extends ViewGroupManager<ReactHori
|
||||
return new ReactHorizontalScrollView(context, mFpsListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object updateState(
|
||||
ReactHorizontalScrollView view,
|
||||
ReactStylesDiffMap props,
|
||||
@Nullable StateWrapper stateWrapper) {
|
||||
view.updateState(stateWrapper);
|
||||
return null;
|
||||
}
|
||||
|
||||
@ReactProp(name = "scrollEnabled", defaultBoolean = true)
|
||||
public void setScrollEnabled(ReactHorizontalScrollView view, boolean value) {
|
||||
view.setScrollEnabled(value);
|
||||
@@ -179,9 +190,9 @@ public class ReactHorizontalScrollViewManager extends ViewGroupManager<ReactHori
|
||||
public void scrollTo(
|
||||
ReactHorizontalScrollView scrollView, ReactScrollViewCommandHelper.ScrollToCommandData data) {
|
||||
if (data.mAnimated) {
|
||||
scrollView.smoothScrollTo(data.mDestX, data.mDestY);
|
||||
scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY);
|
||||
} else {
|
||||
scrollView.scrollTo(data.mDestX, data.mDestY);
|
||||
scrollView.reactScrollTo(data.mDestX, data.mDestY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,9 +203,9 @@ public class ReactHorizontalScrollViewManager extends ViewGroupManager<ReactHori
|
||||
// ScrollView always has one child - the scrollable area
|
||||
int right = scrollView.getChildAt(0).getWidth() + scrollView.getPaddingRight();
|
||||
if (data.mAnimated) {
|
||||
scrollView.smoothScrollTo(right, scrollView.getScrollY());
|
||||
scrollView.reactSmoothScrollTo(right, scrollView.getScrollY());
|
||||
} else {
|
||||
scrollView.scrollTo(right, scrollView.getScrollY());
|
||||
scrollView.reactScrollTo(right, scrollView.getScrollY());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user