Summary:
This PR (initially created for edge-to-edge opt-in support, rebased multiple times) fixes the `Dimensions` API `window` values on Android < 15, when edge-to-edge is enabled.
Currently the window height doesn't include the status and navigation bar heights (but it does on Android >= 15):
<img width="300" alt="Screenshot 2025-06-27 at 16 23 02" src="https://github.com/user-attachments/assets/c7d11334-9298-4f7f-a75c-590df8cc2d8a" />
Using `WindowMetricsCalculator` from AndroidX:
<img width="300" alt="Screenshot 2025-06-27 at 16 34 01" src="https://github.com/user-attachments/assets/7a4e3dc7-a83b-421b-8f6d-fd1344f5fe81" />
Fixes https://github.com/facebook/react-native/issues/47080
## Changelog:
[Android] [Fixed] Fix `Dimensions` `window` values on Android < 15 when edge-to-edge is enabled
Pull Request resolved: https://github.com/facebook/react-native/pull/52738
Test Plan:
Run the example app on an Android < 15 device.
Rollback Plan:
Reviewed By: cipolleschi, Abbondanzo
Differential Revision: D78738516
Pulled By: alanleedev
fbshipit-source-id: fdb22f3cc76b0bda987db426cb015124bcacdc84
Summary:
This PR (initially created for edge-to-edge opt-in support, rebased multiple times) fixes the `Dimensions` API `window` values on Android < 15, when edge-to-edge is enabled.
Currently the window height doesn't include the status and navigation bar heights (but it does on Android >= 15):
<img width="300" alt="Screenshot 2025-06-27 at 16 23 02" src="https://github.com/user-attachments/assets/c7d11334-9298-4f7f-a75c-590df8cc2d8a" />
Using `WindowMetricsCalculator` from AndroidX:
<img width="300" alt="Screenshot 2025-06-27 at 16 34 01" src="https://github.com/user-attachments/assets/7a4e3dc7-a83b-421b-8f6d-fd1344f5fe81" />
Fixes https://github.com/facebook/react-native/issues/47080
## Changelog:
[Android] [Fixed] Fix `Dimensions` `window` values on Android < 15 when edge-to-edge is enabled
Pull Request resolved: https://github.com/facebook/react-native/pull/47554
Test Plan:
Run the example app on an Android < 15 device.
Rollback Plan:
Reviewed By: cortinico
Differential Revision: D77547628
Pulled By: alanleedev
fbshipit-source-id: 9d841f642d5b7ef3294dfbf3868137087a672ad6
Summary:
This follows https://github.com/facebook/react-native/pull/47554
Compared to the initial proposal, I had to remove the `edgeToEdgeEnabled` property from the root `gradle.properties` and put it in the app `gradle.properties` instead (explaining the `AgpConfiguratorUtils.kt` / `GenerateEntryPointTask.kt` / `ProjectUtils.kt` / `PropertyUtils.kt` changes)
This PR:
- Enable edge-to-edge for `MainActivity` (when `edgeToEdgeEnabled` is set to `true`)
- Disable `StatusBar` `backgroundColor` and `translucent` (when `edgeToEdgeEnabled` is set to `true`)
- Enforce `statusBarTranslucent` and `navigationBarTranslucent` on `Modal` when edge-to-edge is enabled
- Add an `isEdgeToEdge` constant to `DeviceInfoModule` for [`react-native-is-edge-to-edge`](https://github.com/zoontek/react-native-edge-to-edge/tree/main/react-native-is-edge-to-edge) detection
## Changelog:
<!-- Help reviewers and the release process by writing your own changelog entry.
Pick one each for the category and type tags:
[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message
For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
-->
- [Android] [Added] - Add edge-to-edge opt-in support
Pull Request resolved: https://github.com/facebook/react-native/pull/52088
Test Plan:
- Update `enableEdgeToEdge` value in `packages/rn-tester/android/app/gradle.properties`
- Recompile
https://github.com/user-attachments/assets/4c6beb98-fa88-427c-b62d-a42ffe5330f0
Rollback Plan:
Reviewed By: cortinico
Differential Revision: D76834213
Pulled By: alanleedev
fbshipit-source-id: c39b2cff1a5e94e31306e3b35651aa2de83d2fe6
Summary:
This PR fixes RNTester system bars background color to match the app one (not solid black).
## Changelog:
- [Internal] [Changed] - Fix RNTester app system bars color when edge-to-edge is enforced
Pull Request resolved: https://github.com/facebook/react-native/pull/51929
Test Plan:
https://github.com/user-attachments/assets/8be0b721-6514-408f-81cd-2106ae7a17c4
Rollback Plan:
Reviewed By: javache
Differential Revision: D76352950
Pulled By: alanleedev
fbshipit-source-id: 474a81564570764a597aa995a0677617263338be
Summary:
Hi 👋
During the [react-native-bootsplash](https://github.com/zoontek/react-native-bootsplash) implementation of the new architecture, I noticed a few thing regarding `RCTRootView` / `RCTFabricSurfaceHostingProxyRootView` compat.
Currently `RCTRootView` inherits from `UIView`, but `RCTFabricSurfaceHostingProxyRootView` does not, which this works:
```obj-c
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps {
RCTRootView *rootView = (RCTRootView *)
[super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
UIView *loadingView = [[storyboard instantiateInitialViewController] view];
loadingView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
loadingView.frame = rootView.bounds;
loadingView.center = (CGPoint){CGRectGetMidX(rootView.bounds), CGRectGetMidY(rootView.bounds)};
loadingView.hidden = NO;
[rootView addSubview:loadingView];
return rootView;
}
```
But this doesn't:
```obj-c
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps {
RCTFabricSurfaceHostingProxyRootView *rootView = (RCTFabricSurfaceHostingProxyRootView *)
[super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
UIView *loadingView = [[storyboard instantiateInitialViewController] view];
loadingView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
loadingView.frame = rootView.bounds;
loadingView.center = (CGPoint){CGRectGetMidX(rootView.bounds), CGRectGetMidY(rootView.bounds)};
loadingView.hidden = NO;
[rootView addSubview:loadingView];
return rootView;
}
```
Because `RCTFabricSurfaceHostingProxyRootView` is an imperfect proxy as it doesn't give access to the underlaying `UIView *`. As a solution, I added a prop on both: `UIView *view`
PS: I'm well aware that `setLoadingView` also exists in both files, but it's currently not usable as the current `isActivityIndicatorViewVisible` / `isSurfaceViewVisible` / `_activityIndicatorViewFactory` logic in `RCTSurfaceHostingView.mm` doesn't work: a situation where `isActivityIndicatorViewVisible == true && isSurfaceViewVisible == false && _activityIndicatorViewFactory != nil` never happen:
<img width="1162" alt="Screenshot_2023-05-06_at_18 10 18" src="https://user-images.githubusercontent.com/1902323/236883439-2256ddfb-7846-482a-b957-002a7d51a148.png">
## Changelog:
<!-- Help reviewers and the release process by writing your own changelog entry.
Pick one each for the category and type tags:
[ANDROID|GENERAL|IOS|INTERNAL] [BREAKING|ADDED|CHANGED|DEPRECATED|REMOVED|FIXED|SECURITY] - Message
For more details, see:
https://reactnative.dev/contributing/changelogs-in-pull-requests
Pull Request resolved: https://github.com/facebook/react-native/pull/37310
Test Plan:
Add this block of code in `AppDelegate.mm`:
```obj-c
#import <React/RCTRootView.h>
#if __has_include(<React/RCTFabricSurfaceHostingProxyRootView.h>)
#import <React/RCTFabricSurfaceHostingProxyRootView.h>
#endif
// …
- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge
moduleName:(NSString *)moduleName
initProps:(NSDictionary *)initProps {
#ifdef RCT_NEW_ARCH_ENABLED
RCTFabricSurfaceHostingProxyRootView *rootView = (RCTFabricSurfaceHostingProxyRootView *)
#else
RCTRootView *rootView = (RCTRootView *)
#endif
[super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps];
// accessing the "real" root view on both arch
UIView *view = rootView.view;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
UIView *loadingView = [[storyboard instantiateInitialViewController] view];
loadingView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
loadingView.frame = view.bounds;
loadingView.center = (CGPoint){CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds)};
loadingView.hidden = NO;
[view addSubview:loadingView];
return rootView;
}
```
It should persist the splash screen on both old and new architecture.
Reviewed By: sammy-SC
Differential Revision: D45688644
Pulled By: cipolleschi
fbshipit-source-id: b6f2fc8091a15189ea2eceb8ea426593f62674cb
Summary:
Following the PR https://github.com/facebook/react-native/pull/6195, this adds a `HEIGHT` constant on `StatusBar` for iOS.
Combined with `statusBarFrameDidChange` and `statusBarFrameWillChange` StatusBar native events, it solves various problems with In-Call cellar bar / Location bar / others 40pt status bars, and offers a correct `keyboardVerticalOffset` value for the KeyboardAvoidingView component.
Closes https://github.com/facebook/react-native/pull/12041
Differential Revision: D4450924
Pulled By: hramos
fbshipit-source-id: 664798260f4226140f3fa3f9222a415a305d0d78