From 8aa87814f62e42741ebb01994796625473c1310f Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Fri, 28 Jan 2022 10:35:59 -0800 Subject: [PATCH] Consider transform when calculating overflowInset values Summary: The fix in this diff seems simple, but it took some time to understand why this change fixed the issue that views animated use native driver out from their parent's layout are not getting touch events. We introduced `overflowInset` to RN Android a while back to give each shadow node extra information to cover all its children's layout. These values (left, top, right, bottom extensions from the view's own layout) help us improve hit-testing algorithm used in touch events. We could ignore all subtrees that the touch point not in their parent's overflowInset box. However, this was not working for native animation. When `userNativeDriver` is on, all animation happens without Fabric knows anything about them. The overflowInset is out of date with the final animated layout, which caused the issue that we ignored the animated view as we thought it's not under the pointer. Here is a playground demo (P476407654) for the issue: https://pxl.cl/1XfPL We've tried to fix this by passing the final animated values via `passthroughAnimatedPropExplicitValues` added in D32539976. This is a prop that will get merged into `style` prop for [animation component](https://fburl.com/code/jybzfgu5). The transform values were already applied when measuring layout in [Pressability](https://fburl.com/code/5mect2k3), which uses [LayoutableShadowNode](https://fburl.com/code/qh8fufrw). However, this is not the case for overflowInset calculation. Hence, the fix here is to apply the transform matrix in Yoga before calculating the overflowInset. Changelog: [Android][Fixed] - Fix overflowInset calculation by using transform values Reviewed By: ShikaSD Differential Revision: D33806030 fbshipit-source-id: e438618e3d6e5b0333cff9ff9919b841d73b2e9d --- .../components/view/YogaLayoutableShadowNode.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp index 005272736083aa..5ba750e4832887 100644 --- a/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +++ b/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp @@ -528,8 +528,17 @@ void YogaLayoutableShadowNode::layout(LayoutContext layoutContext) { } if (yogaNode_.getStyle().overflow() == YGOverflowVisible) { + auto transform = getTransform(); + auto transformedContentFrame = contentFrame; + if (Transform::Identity() != transform) { + // When animation uses native driver, Yoga has no knowledge of the + // animation. In case the content goes out from current container, we need + // to union the content frame with its transformed frame. + transformedContentFrame = contentFrame * getTransform(); + transformedContentFrame.unionInPlace(contentFrame); + } layoutMetrics_.overflowInset = - calculateOverflowInset(layoutMetrics_.frame, contentFrame); + calculateOverflowInset(layoutMetrics_.frame, transformedContentFrame); } else { layoutMetrics_.overflowInset = {}; }