diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp index a8ecce51c482f7..9589ea9dc58c79 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.cpp @@ -63,9 +63,11 @@ void ScrollViewShadowNode::layout(LayoutContext layoutContext) { updateStateIfNeeded(); } -Point ScrollViewShadowNode::getContentOriginOffset() const { +Point ScrollViewShadowNode::getContentOriginOffset( + bool includeTransform) const { auto stateData = getStateData(); auto contentOffset = stateData.contentOffset; + return {-contentOffset.x, -contentOffset.y + stateData.scrollAwayPaddingTop}; } diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.h b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.h index cc4d7e119cc2d1..a0fbcf4ca1e9a1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewShadowNode.h @@ -37,7 +37,7 @@ class ScrollViewShadowNode final : public ConcreteViewShadowNode< #pragma mark - LayoutableShadowNode void layout(LayoutContext layoutContext) override; - Point getContentOriginOffset() const override; + Point getContentOriginOffset(bool includeTransform) const override; private: void updateStateIfNeeded(); diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp index 5ddb4c38996850..90c2a578cbb3fa 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.cpp @@ -151,7 +151,11 @@ LayoutMetrics LayoutableShadowNode::computeRelativeLayoutMetrics( } if (i != 0 && policy.includeTransform) { - resultFrame.origin += currentShadowNode->getContentOriginOffset(); + // Transformation is not applied here and instead we delegated out in + // getContentOriginOffset. The reason is that for `ScrollViewShadowNode`, + // we need to consider `scrollAwayPaddingTop` which should NOT be included + // in the transform. + resultFrame.origin += currentShadowNode->getContentOriginOffset(true); } if (policy.enableOverflowClipping) { @@ -189,6 +193,11 @@ Transform LayoutableShadowNode::getTransform() const { } Point LayoutableShadowNode::getContentOriginOffset() const { + return getContentOriginOffset(false); +} + +Point LayoutableShadowNode::getContentOriginOffset( + bool includeTransform) const { return {0, 0}; } diff --git a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h index cae02ce15d1ab3..54c76e78f8d6ff 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/LayoutableShadowNode.h @@ -125,6 +125,13 @@ class LayoutableShadowNode : public ShadowNode { */ virtual Point getContentOriginOffset() const; + /* + * Returns offset which is applied to children's origin in + * `LayoutableShadowNode::getRelativeLayoutMetrics` and + * `LayoutableShadowNode::findNodeAtPoint`. + */ + virtual Point getContentOriginOffset(bool includeTransform) const; + /* * Sets layout metrics for the shadow node. */ diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/TestComponent.h b/packages/react-native/ReactCommon/react/renderer/core/tests/TestComponent.h index b3f5fefe499331..b0715274d3c624 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/TestComponent.h +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/TestComponent.h @@ -76,7 +76,8 @@ class TestShadowNode final : public ConcreteViewShadowNode< facebook::react::Point _contentOriginOffset{}; - facebook::react::Point getContentOriginOffset() const override { + facebook::react::Point getContentOriginOffset( + bool includeTransform) const override { return _contentOriginOffset; } };