mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix ScrollView state not being set if scrollTo command was called
Summary: # Problem `UIManager::getRelativeLayoutMetrics` returns incorrect `frame.origin.y` value. Just quick reiteration how calculation of `frame.origin` works. We take frame of the target shadow node, travers hierarchy to the root and keep adding `frame.origin` of each ancestor to target shadow node's origin. One more important piece of information, to calculate scroll view's `frame.origin`, we need to have its contentOffset which gets passed to Fabric core through state. # So where does it go wrong? Problem is that on Android, calling view command `scrollTo` doesn't set its internal state correctly. So when we calculate the layoutmetrics, scroll view's `frame.origin` is off by whatever value was used in `scrollTo`. # The fix In `ReactScrollView`, correctly set state after `scrollTo` is called on it. Changelog: [Internal] Reviewed By: JoshuaGross Differential Revision: D19835549 fbshipit-source-id: d56e7b0b05023c0497e52c8b46fdcf58ca78b4a5
This commit is contained in:
committed by
Facebook Github Bot
parent
14ac53363e
commit
b07a65b9d9
@@ -200,7 +200,7 @@ public class ReactScrollView extends ScrollView
|
||||
@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());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -597,7 +597,7 @@ public class ReactScrollView extends ScrollView
|
||||
targetOffset = currentPage * interval;
|
||||
if (targetOffset != currentOffset) {
|
||||
mActivelyScrolling = true;
|
||||
smoothScrollTo(getScrollX(), (int) targetOffset);
|
||||
reactSmoothScrollTo(getScrollX(), (int) targetOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,7 +715,7 @@ public class ReactScrollView extends ScrollView
|
||||
|
||||
postInvalidateOnAnimation();
|
||||
} else {
|
||||
smoothScrollTo(getScrollX(), targetOffset);
|
||||
reactSmoothScrollTo(getScrollX(), targetOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -768,6 +768,28 @@ public class ReactScrollView extends ScrollView
|
||||
mContentView = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a mContentView's layout has changed. Fixes the scroll position if it's too large
|
||||
* after the content resizes. Without this, the user would see a blank ScrollView when the scroll
|
||||
@@ -791,7 +813,7 @@ public class ReactScrollView extends ScrollView
|
||||
int currentScrollY = getScrollY();
|
||||
int maxScrollY = getMaxScrollY();
|
||||
if (currentScrollY > maxScrollY) {
|
||||
scrollTo(getScrollX(), maxScrollY);
|
||||
reactScrollTo(getScrollX(), maxScrollY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -201,9 +201,9 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
|
||||
public void scrollTo(
|
||||
ReactScrollView 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,9 +275,9 @@ public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
|
||||
// ScrollView always has one child - the scrollable area
|
||||
int bottom = scrollView.getChildAt(0).getHeight() + scrollView.getPaddingBottom();
|
||||
if (data.mAnimated) {
|
||||
scrollView.smoothScrollTo(scrollView.getScrollX(), bottom);
|
||||
scrollView.reactSmoothScrollTo(scrollView.getScrollX(), bottom);
|
||||
} else {
|
||||
scrollView.scrollTo(scrollView.getScrollX(), bottom);
|
||||
scrollView.reactScrollTo(scrollView.getScrollX(), bottom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user