mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
fix view culling in RTL languages (#52602)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52602 changelog: [internal] fixes RTL issue in View Culling where scroll view offset was not correctly adjusted for RTL. The example failing case is described in a test. Reviewed By: lenaic Differential Revision: D78322759 fbshipit-source-id: d60d98aa45d4d9b576b133990f64ef941e6618e8
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f004cd39bc
commit
f3b6eeb96e
Vendored
+53
@@ -2556,3 +2556,56 @@ describe('culling inside ScrollView with overflow visible', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('horizontal ScrollView in RTL script', () => {
|
||||
it('renders item 1', () => {
|
||||
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ScrollView
|
||||
style={{direction: 'rtl', height: 100, width: 100}}
|
||||
horizontal={true}>
|
||||
<View nativeID={'item1'} style={{height: 90, width: 90, margin: 5}} />
|
||||
<View nativeID={'item2'} style={{height: 90, width: 90, margin: 5}} />
|
||||
</ScrollView>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root.takeMountingManagerLogs()).toEqual([
|
||||
'Update {type: "RootView", nativeID: (root)}',
|
||||
'Create {type: "ScrollView", nativeID: (N/A)}',
|
||||
'Create {type: "AndroidHorizontalScrollContentView", nativeID: (N/A)}',
|
||||
'Create {type: "View", nativeID: "item1"}',
|
||||
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "item1"}',
|
||||
'Insert {type: "AndroidHorizontalScrollContentView", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
|
||||
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
|
||||
]);
|
||||
});
|
||||
|
||||
it('takes contentOffset into account', () => {
|
||||
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
|
||||
|
||||
Fantom.runTask(() => {
|
||||
root.render(
|
||||
<ScrollView
|
||||
style={{direction: 'rtl', height: 100, width: 100}}
|
||||
horizontal={true}
|
||||
contentOffset={{x: 100, y: 0}}>
|
||||
<View nativeID={'item1'} style={{height: 90, width: 90, margin: 5}} />
|
||||
<View nativeID={'item2'} style={{height: 90, width: 90, margin: 5}} />
|
||||
</ScrollView>,
|
||||
);
|
||||
});
|
||||
|
||||
expect(root.takeMountingManagerLogs()).toEqual([
|
||||
'Update {type: "RootView", nativeID: (root)}',
|
||||
'Create {type: "ScrollView", nativeID: (N/A)}',
|
||||
'Create {type: "AndroidHorizontalScrollContentView", nativeID: (N/A)}',
|
||||
'Create {type: "View", nativeID: "item2"}',
|
||||
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "item2"}',
|
||||
'Insert {type: "AndroidHorizontalScrollContentView", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
|
||||
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,12 +25,24 @@ CullingContext CullingContext::adjustCullingContextIfNeeded(
|
||||
dynamic_cast<const ScrollViewShadowNode*>(pair.shadowNode)) {
|
||||
if (scrollViewShadowNode->getConcreteProps().yogaStyle.overflow() !=
|
||||
yoga::Overflow::Visible) {
|
||||
auto layoutMetrics = scrollViewShadowNode->getLayoutMetrics();
|
||||
cullingContext.frame.origin =
|
||||
-scrollViewShadowNode->getContentOriginOffset(
|
||||
/* includeTransform */ true);
|
||||
cullingContext.frame.size =
|
||||
scrollViewShadowNode->getLayoutMetrics().frame.size;
|
||||
cullingContext.transform = Transform::Identity();
|
||||
|
||||
if (layoutMetrics.layoutDirection == LayoutDirection::RightToLeft) {
|
||||
// In RTL, content offset is flipped horizontally.
|
||||
// We need to flip the culling context frame to match.
|
||||
// See:
|
||||
// https://github.com/facebook/react-native/blob/c2f39cfdd87c32b9a59efe8a788b8a03f02b0ea0/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm#L579
|
||||
auto stateData = scrollViewShadowNode->getStateData();
|
||||
cullingContext.frame.origin.x =
|
||||
stateData.contentBoundingRect.size.width -
|
||||
layoutMetrics.frame.size.width - cullingContext.frame.origin.x;
|
||||
}
|
||||
} else {
|
||||
cullingContext = {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user