Fix Yoga's right to left offset in horizontal scroll view
Summary:
Changelog: [internal]
Yoga offsets content view of scrollview in RTL environment. React Native Classis deals with it by using a separate component [ScrollContentView](6e6443afd0/React/Views/ScrollView/RCTScrollContentShadowView.m (L18-L25)
) and making the adjustment there.
In New React Native Renderer, it can be handled inside `ScrollViewShadowNode`.
Reviewed By: JoshuaGross
Differential Revision: D26817121
fbshipit-source-id: ad48374ef19b802d25e919ac0aae05c5890762f2
This commit is contained in:
Родитель
772fbf0a7d
Коммит
283512cc42
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "ScrollViewShadowNode.h"
|
||||
|
||||
#include <react/debug/react_native_assert.h>
|
||||
#include <react/renderer/core/LayoutMetrics.h>
|
||||
|
||||
namespace facebook {
|
||||
|
@ -30,10 +31,31 @@ void ScrollViewShadowNode::updateStateIfNeeded() {
|
|||
}
|
||||
}
|
||||
|
||||
void ScrollViewShadowNode::updateScrollContentOffsetIfNeeded() {
|
||||
#ifndef ANDROID
|
||||
react_native_assert(
|
||||
children_->size() == 1 && "ScrollView only has single child");
|
||||
if (getLayoutMetrics().layoutDirection == LayoutDirection::RightToLeft) {
|
||||
// Yoga place `contentView` on the right side of `scrollView` when RTL
|
||||
// layout is enforced. To correct for this, in RTL setting, correct the
|
||||
// frame's origin. React Native Classic does this as well in
|
||||
// `RCTScrollContentShadowView.m`.
|
||||
for (auto layoutableNode : getLayoutableChildNodes()) {
|
||||
auto layoutMetrics = layoutableNode->getLayoutMetrics();
|
||||
if (layoutMetrics.frame.origin.x != 0) {
|
||||
layoutMetrics.frame.origin.x = 0;
|
||||
layoutableNode->setLayoutMetrics(layoutMetrics);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
void ScrollViewShadowNode::layout(LayoutContext layoutContext) {
|
||||
ConcreteViewShadowNode::layout(layoutContext);
|
||||
updateScrollContentOffsetIfNeeded();
|
||||
updateStateIfNeeded();
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class ScrollViewShadowNode final : public ConcreteViewShadowNode<
|
|||
|
||||
private:
|
||||
void updateStateIfNeeded();
|
||||
void updateScrollContentOffsetIfNeeded();
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
|
|
|
@ -62,6 +62,10 @@ class YogaDirtyFlagTest : public ::testing::Test {
|
|||
Element<ScrollViewShadowNode>()
|
||||
.reference(scrollViewShadowNode_)
|
||||
.tag(7)
|
||||
.children({
|
||||
Element<ViewShadowNode>()
|
||||
.tag(8)
|
||||
})
|
||||
})
|
||||
});
|
||||
// clang-format on
|
||||
|
|
|
@ -77,11 +77,14 @@ TEST(StateReconciliationTest, testStateReconciliation) {
|
|||
.reference(shadowNodeAB)
|
||||
.children({
|
||||
Element<ViewShadowNode>()
|
||||
.reference(shadowNodeABA),
|
||||
Element<ViewShadowNode>()
|
||||
.reference(shadowNodeABB),
|
||||
Element<ViewShadowNode>()
|
||||
.reference(shadowNodeABC)
|
||||
.children({
|
||||
Element<ViewShadowNode>()
|
||||
.reference(shadowNodeABA),
|
||||
Element<ViewShadowNode>()
|
||||
.reference(shadowNodeABB),
|
||||
Element<ViewShadowNode>()
|
||||
.reference(shadowNodeABC)
|
||||
})
|
||||
})
|
||||
});
|
||||
// clang-format on
|
||||
|
|
Загрузка…
Ссылка в новой задаче