Skip to content

Conversation

@pmleczek
Copy link
Collaborator

@pmleczek pmleczek commented Nov 28, 2025

Changes

  • SwiftUI view is now created from ReactNativeViewController instead of ReactNativeHostManager.loadView() - allows for unified pop gesture control
  • Removed any settings related to presentation on iOS (e.g. title bar visibility or safe area ignoring) - it should be configurable by the developer according to their project needs
  • Added setNativeBackEnabled method to the Expo module:

Description

  • Accepts a boolean - whether back events (pop gesture/back button) should be handled by the native (host) app.
  • Platform specific behavior:
    • On iOS updates interactivePopGestureRecognizer value and modifies gestureRecognizers responsible for handling the pop gesture.
    • On Android introduces a shared brownfield navigation state which controls whether back action is handled natively or emitted to RN via DeviceEventManagerModule.
  • Doesn't affect popToNative which always pops the React Native view.

Example of usage:

const Screen = () => {
    const navigation = useNavigation();
  
    useEffect(() => {
      // Native back action is enabled only if we can't go back within RN app
      const unsubscribe = navigation.addListener("state", () => {
        const shouldEnableNativeBack = navigation.canGoBack();
        ExpoBrownfield.setNativeBackEnabled(!shouldEnableNativeBack);
      });
  
      return () => {
        unsubscribe();
      };
    }, [navigation]);

Videos

Android

Screen.Recording.2025-11-28.at.19.33.18.mov

iOS (UIKit)

Screen.Recording.2025-11-28.at.19.35.34.mov

iOS (SwiftUI)

Screen.Recording.2025-11-28.at.19.38.06.mov

@pmleczek pmleczek self-assigned this Nov 28, 2025
@pmleczek
Copy link
Collaborator Author

@gabrieldonadel

Copy link

@gabrieldonadel gabrieldonadel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Comment on lines +94 to +100
val reactContext = reactHost?.currentReactContext
if (reactContext != null) {
val deviceEventManager = reactContext.getNativeModule(
DeviceEventManagerModule::class.java
)
deviceEventManager?.emitHardwareBackPressed()
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val reactContext = reactHost?.currentReactContext
if (reactContext != null) {
val deviceEventManager = reactContext.getNativeModule(
DeviceEventManagerModule::class.java
)
deviceEventManager?.emitHardwareBackPressed()
}
val reactContext = reactHost?.currentReactContext?.let { reactContext ->
val deviceEventManager = reactContext.getNativeModule(
DeviceEventManagerModule::class.java
)
deviceEventManager?.emitHardwareBackPressed()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants