mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fix content origin offset for RTL scripts
Summary: changelog: [internal] There were three separate problems preventing measure infra to work correctly with views inside horizontal scroll view in RTL environment. 1. Initial offset is wasn't communicated to Fabric. This is resolved separately as it doesn't affect only RTL: D26778991 (https://github.com/facebook/react-native/commit/630ac87591eb9d535bc32c6c42c624bfc3f1953f). 3. On Android when layout direction is RTL, offset of scrollview is calculated from right. Reviewed By: mdvacca Differential Revision: D26779860 fbshipit-source-id: 61572c78091a1f5417102eb38d88ba7d172e6102
This commit is contained in:
committed by
Facebook GitHub Bot
parent
fc032cd8d8
commit
365e12430a
+1
-1
@@ -64,7 +64,7 @@ public class ReactHorizontalScrollContainerView extends ReactViewGroup {
|
||||
// Call with the present values in order to re-layout if necessary
|
||||
ReactHorizontalScrollView parent = (ReactHorizontalScrollView) getParent();
|
||||
// Fix the ScrollX position when using RTL language
|
||||
int offsetX = parent.getScrollX() + getWidth() - mCurrentWidth;
|
||||
int offsetX = parent.getScrollX() + getWidth() - mCurrentWidth - parent.getWidth();
|
||||
parent.reactScrollTo(offsetX, parent.getScrollY());
|
||||
}
|
||||
}
|
||||
|
||||
+30
-13
@@ -25,7 +25,6 @@ import android.view.accessibility.AccessibilityEvent;
|
||||
import android.widget.HorizontalScrollView;
|
||||
import android.widget.OverScroller;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.text.TextUtilsCompat;
|
||||
import androidx.core.view.AccessibilityDelegateCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
@@ -34,6 +33,7 @@ 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.modules.i18nmanager.I18nUtil;
|
||||
import com.facebook.react.uimanager.FabricViewStateManager;
|
||||
import com.facebook.react.uimanager.MeasureSpecAssertions;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
@@ -45,7 +45,6 @@ import com.facebook.react.views.view.ReactViewBackgroundManager;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/** Similar to {@link ReactScrollView} but only supports horizontal scrolling. */
|
||||
public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
@@ -55,6 +54,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
private static boolean sTriedToGetScrollerField = false;
|
||||
private static final String CONTENT_OFFSET_LEFT = "contentOffsetLeft";
|
||||
private static final String CONTENT_OFFSET_TOP = "contentOffsetTop";
|
||||
private int mLayoutDirection;
|
||||
|
||||
private static final int UNSET_CONTENT_OFFSET = -1;
|
||||
|
||||
@@ -124,6 +124,10 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
});
|
||||
|
||||
mScroller = getOverScrollerFromParent();
|
||||
mLayoutDirection =
|
||||
I18nUtil.getInstance().isRTL(context)
|
||||
? ViewCompat.LAYOUT_DIRECTION_RTL
|
||||
: ViewCompat.LAYOUT_DIRECTION_LTR;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -401,7 +405,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
if (getChildCount() > 0) {
|
||||
View currentFocused = findFocus();
|
||||
View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
|
||||
View rootChild = getChildAt(0);
|
||||
View rootChild = getContentView();
|
||||
if (rootChild != null && nextFocused != null && nextFocused.getParent() == rootChild) {
|
||||
if (!isScrolledInView(nextFocused) && !isMostlyScrolledInView(nextFocused)) {
|
||||
smoothScrollToNextPage(direction);
|
||||
@@ -532,7 +536,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
Assertions.assertNotNull(mClippingRect);
|
||||
|
||||
ReactClippingViewGroupHelper.calculateClippingRect(this, mClippingRect);
|
||||
View contentView = getChildAt(0);
|
||||
View contentView = getContentView();
|
||||
if (contentView instanceof ReactClippingViewGroup) {
|
||||
((ReactClippingViewGroup) contentView).updateClippingRect();
|
||||
}
|
||||
@@ -555,6 +559,11 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
return getWidth();
|
||||
}
|
||||
|
||||
private View getContentView() {
|
||||
View contentView = getChildAt(0);
|
||||
return contentView;
|
||||
}
|
||||
|
||||
public void setEndFillColor(int color) {
|
||||
if (color != mEndFillColor) {
|
||||
mEndFillColor = color;
|
||||
@@ -608,7 +617,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mEndFillColor != Color.TRANSPARENT) {
|
||||
final View content = getChildAt(0);
|
||||
final View content = getContentView();
|
||||
if (mEndBackground != null && content != null && content.getRight() < getWidth()) {
|
||||
mEndBackground.setBounds(content.getRight(), 0, getWidth(), getHeight());
|
||||
mEndBackground.draw(canvas);
|
||||
@@ -805,10 +814,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
int width = getWidth() - ViewCompat.getPaddingStart(this) - ViewCompat.getPaddingEnd(this);
|
||||
|
||||
// offsets are from the right edge in RTL layouts
|
||||
boolean isRTL =
|
||||
TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault())
|
||||
== ViewCompat.LAYOUT_DIRECTION_RTL;
|
||||
if (isRTL) {
|
||||
if (mLayoutDirection == LAYOUT_DIRECTION_RTL) {
|
||||
targetOffset = maximumOffset - targetOffset;
|
||||
velocityX = -velocityX;
|
||||
}
|
||||
@@ -847,7 +853,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
// if scrolling after the last snap offset and snapping to the
|
||||
// end of the list is disabled, then we allow free scrolling
|
||||
int currentOffset = getScrollX();
|
||||
if (isRTL) {
|
||||
if (mLayoutDirection == LAYOUT_DIRECTION_RTL) {
|
||||
currentOffset = maximumOffset - currentOffset;
|
||||
}
|
||||
if (!mSnapToEnd && targetOffset >= lastOffset) {
|
||||
@@ -881,7 +887,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
// Make sure the new offset isn't out of bounds
|
||||
targetOffset = Math.min(Math.max(0, targetOffset), maximumOffset);
|
||||
|
||||
if (isRTL) {
|
||||
if (mLayoutDirection == LAYOUT_DIRECTION_RTL) {
|
||||
targetOffset = maximumOffset - targetOffset;
|
||||
velocityX = -velocityX;
|
||||
}
|
||||
@@ -1041,7 +1047,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
* @param y
|
||||
*/
|
||||
private void setPendingContentOffsets(int x, int y) {
|
||||
View child = getChildAt(0);
|
||||
View child = getContentView();
|
||||
if (child != null && child.getWidth() != 0 && child.getHeight() != 0) {
|
||||
pendingContentOffsetX = UNSET_CONTENT_OFFSET;
|
||||
pendingContentOffsetY = UNSET_CONTENT_OFFSET;
|
||||
@@ -1063,12 +1069,23 @@ public class ReactHorizontalScrollView extends HorizontalScrollView
|
||||
mLastStateUpdateScrollX = scrollX;
|
||||
mLastStateUpdateScrollY = scrollY;
|
||||
|
||||
final int fabricScrollX;
|
||||
if (mLayoutDirection == LAYOUT_DIRECTION_RTL) {
|
||||
// getScrollX returns offset from left even when layout direction is RTL.
|
||||
// The following line calculates offset from right.
|
||||
View child = getContentView();
|
||||
int contentWidth = child != null ? child.getWidth() : 0;
|
||||
fabricScrollX = -(contentWidth - scrollX - getWidth());
|
||||
} else {
|
||||
fabricScrollX = scrollX;
|
||||
}
|
||||
|
||||
mFabricViewStateManager.setState(
|
||||
new FabricViewStateManager.StateUpdateCallback() {
|
||||
@Override
|
||||
public WritableMap getStateUpdate() {
|
||||
WritableMap map = new WritableNativeMap();
|
||||
map.putDouble(CONTENT_OFFSET_LEFT, PixelUtil.toDIPFromPixel(scrollX));
|
||||
map.putDouble(CONTENT_OFFSET_LEFT, PixelUtil.toDIPFromPixel(fabricScrollX));
|
||||
map.putDouble(CONTENT_OFFSET_TOP, PixelUtil.toDIPFromPixel(scrollY));
|
||||
return map;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user