diff --git a/apps/src/shared/PressableWithFeedback.tsx b/apps/src/shared/PressableWithFeedback.tsx index df629faa5c..21bcf72db7 100644 --- a/apps/src/shared/PressableWithFeedback.tsx +++ b/apps/src/shared/PressableWithFeedback.tsx @@ -45,6 +45,7 @@ const PressableWithFeedback = React.forwardRef((props: PressableProps, ref: Forw return ( = { + navigation: NativeStackNavigationProp; +}; + +type StackNavigationProp = NavigationProp; + +const Stack = createNativeStackNavigator(); + +interface Configuration { + size: 'sm' | 'md' | 'lg'; + hidesSharedBackground: boolean; + hitSlop: '0' | '10' | '30'; + pressRetentionOffset: '0' | '20' | '50'; +} + +function getPressableFromConfig(config: Configuration) { + return ( + + + + ); +} + +function Screen({ navigation }: StackNavigationProp) { + const [config, setConfig] = useState({ + size: 'sm', + hidesSharedBackground: true, + hitSlop: '0', + pressRetentionOffset: '0', + }); + + useEffect(() => { + navigation.setOptions({ + unstable_headerLeftItems: () => [ + { + type: 'custom', + element: getPressableFromConfig(config), + hidesSharedBackground: config.hidesSharedBackground, + }, + ], + unstable_headerRightItems: () => [ + { + type: 'custom', + element: getPressableFromConfig(config), + hidesSharedBackground: config.hidesSharedBackground, + }, + ], + }); + }, [config, navigation]); + + return ( + + + {getPressableFromConfig(config)} + + + setConfig({ ...config, hidesSharedBackground: value }) + } + /> + + label="size" + value={config.size} + onValueChange={value => + setConfig({ + ...config, + size: value, + }) + } + items={['sm', 'md', 'lg']} + /> + + label="hitSlop" + value={config.hitSlop} + onValueChange={value => + setConfig({ + ...config, + hitSlop: value, + }) + } + items={['0', '10', '30']} + /> + + label="pressRetentionOffset" + value={config.pressRetentionOffset} + onValueChange={value => + setConfig({ + ...config, + pressRetentionOffset: value, + }) + } + items={['0', '20', '50']} + /> + + ); +} + +export default function App() { + return ( + + + + + + ); +} diff --git a/apps/src/tests/index.ts b/apps/src/tests/index.ts index 151ef70a9b..f1219d5a76 100644 --- a/apps/src/tests/index.ts +++ b/apps/src/tests/index.ts @@ -165,6 +165,7 @@ export { default as Test3369 } from './Test3369'; export { default as Test3379 } from './Test3379'; export { default as Test3422 } from './Test3422'; export { default as Test3425 } from './Test3425'; +export { default as Test3446 } from './Test3446'; export { default as TestScreenAnimation } from './TestScreenAnimation'; // The following test was meant to demo the "go back" gesture using Reanimated // but the associated PR in react-navigation is currently put on hold diff --git a/ios/RNSScreenStack.mm b/ios/RNSScreenStack.mm index b77b87f469..498b81db0d 100644 --- a/ios/RNSScreenStack.mm +++ b/ios/RNSScreenStack.mm @@ -1129,7 +1129,8 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event RNSScreenView *topMostScreen = (RNSScreenView *)_reactSubviews.lastObject; UIView *headerConfig = topMostScreen.findHeaderConfig; if ([headerConfig isKindOfClass:[RNSScreenStackHeaderConfig class]]) { - UIView *headerHitTestResult = [headerConfig hitTest:point withEvent:event]; + CGPoint convertedPoint = [self convertPoint:point toView:headerConfig]; + UIView *headerHitTestResult = [headerConfig hitTest:convertedPoint withEvent:event]; if (headerHitTestResult != nil) { return headerHitTestResult; } diff --git a/ios/RNSScreenStackHeaderConfig.mm b/ios/RNSScreenStackHeaderConfig.mm index 5cc6622d8d..3270127a09 100644 --- a/ios/RNSScreenStackHeaderConfig.mm +++ b/ios/RNSScreenStackHeaderConfig.mm @@ -169,19 +169,17 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event continue; } - // we wrap the headerLeft/Right component in a UIBarButtonItem - // so we need to hit test subviews from left to right, because of the view flattening - UIView *headerComponent = nil; - for (UIView *headerComponentSubview in subview.subviews) { + // We wrap the headerLeft/Right component in a UIBarButtonItem + // so we need to hit test subviews, because of the view flattening + // (we match RCTViewComponentView implementation). + for (UIView *headerComponentSubview in [subview.subviews reverseObjectEnumerator]) { CGPoint convertedPoint = [self convertPoint:point toView:headerComponentSubview]; UIView *hitTestResult = [headerComponentSubview hitTest:convertedPoint withEvent:event]; if (hitTestResult != nil) { - headerComponent = hitTestResult; + return hitTestResult; } } - - return headerComponent; } } return nil;