Commit Graph
9 Commits
Author SHA1 Message Date
Mathieu ActhernoeneandFacebook GitHub Bot 3b185e4bce Fix Dimensions window values on Android < 15 (#52738)
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
2025-08-07 02:17:14 -07:00
Mathieu ActhernoeneandFacebook GitHub Bot 86994a6e22 Fix Dimensions window values on Android < 15 (#52481)
Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/52481

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: D77906644

Pulled By: alanleedev

fbshipit-source-id: 121cd6bc4133973f06b28eb9e79c9387ac7070a1
2025-07-16 09:15:43 -07:00
Mathieu ActhernoeneandFacebook GitHub Bot 85d10ed904 Fix Dimensions window values on Android < 15 (#47554)
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
2025-07-03 11:37:55 -07:00
Mathieu ActhernoeneandFacebook GitHub Bot 09ef774ff6 Add edge-to-edge opt-in support (#52088)
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
2025-06-27 06:16:23 -07:00
Mathieu ActhernoeneandFacebook GitHub Bot 3c17e101ee Add UiModeUtils.isDarkMode helper (#51925)
Summary:
This PR is part of the [edge-to-edge core implementation effort](https://github.com/facebook/react-native/pull/47554). It adds a helper to `ContextUtils`, called `isDarkMode` in order to be reused accross the Android codebase.

## Changelog:

- [Internal] [Added] - Add `UiModeUtils.isDarkMode` helper

Pull Request resolved: https://github.com/facebook/react-native/pull/51925

Test Plan:
<img width="300" alt="Screenshot 2025-06-10 at 17 50 19" src="https://github.com/user-attachments/assets/48795406-e852-486a-bae8-54507ad769ee" />

<img width="300" alt="Screenshot 2025-06-10 at 17 50 42" src="https://github.com/user-attachments/assets/0dbdece9-04f7-487b-ace8-4786c8da381d" />

Rollback Plan:

Reviewed By: cortinico

Differential Revision: D76352849

Pulled By: alanleedev

fbshipit-source-id: fbbc772d1dfa3e30e62a71a711de11b85cdec446
2025-06-16 10:35:35 -07:00
Mathieu ActhernoeneandFacebook GitHub Bot b5be57cb76 Fix RNTester system bars background when edge-to-edge is enforced (#51929)
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
2025-06-13 11:05:35 -07:00
Mathieu ActhernoeneandFacebook GitHub Bot 7a6c7a462a feat(android): Edge-to-edge Modal (navigationBarTranslucent prop) (#47254)
Summary:
The future of Android is [edge-to-edge](https://github.com/react-native-community/discussions-and-proposals/discussions/827) and to make the React Native developer experience seamless in this regard, the ecosystem needs to transition from “opaque system bars by default” to “edge-to-edge by default.”

Currently, there's no easy way to have edge-to-edge modals, as they are implemented using `Dialog` instances (a separate `Window`) and only provide a `statusBarTranslucent` prop.

I tried to implement it in [`react-native-edge-to-edge`](https://github.com/zoontek/react-native-edge-to-edge) by listening to the `topShow` `UIManager` event. But if it works well when there's a defined animation, we can see a quick jump when there's none, because there's too much delay before the event, and edge-to-edge cannot be applied quick enough to the dialog window.

### react-native-edge-to-edge implem with animation (no jump)

https://github.com/user-attachments/assets/4933a102-87a5-40e4-98d9-47f8c0817592

### react-native-edge-to-edge implem without animation (jump)

https://github.com/user-attachments/assets/e4675589-08fe-44fe-b9d8-0a6b3552b461

 ---

For this reason, and because listening to event feels a bit hacky, I think it will be better to go for a new prop directly on RN Modal component: `navigationBarTranslucent`

> [!NOTE]
> `navigationBarTranslucent` cannot be used without `statusBarTranslucent`, as setting both enable edge-to-edge, like [AndroidX would do](https://github.com/androidx/androidx/blob/androidx-main/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt) and it would requires extra (and unecessary, given the direction Android is taking) work to find a way to keep the status bar opaque but the navigation bar transparent that work on Android 6 to 15+

### Additional infos

- Colors used for the buttons navigation bar in the PR are the default Android ones ([light](https://github.com/androidx/androidx/blob/androidx-main/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt#L37) and [dark](https://github.com/androidx/androidx/blob/androidx-main/activity/activity/src/main/java/androidx/activity/EdgeToEdge.kt#L42))
- Compared to the Google implementation, the light scrim is applied from `O_MR1` to `Q` (and not `O` to `Q`) as the [`android:windowLightNavigationBar`](https://developer.android.com/reference/android/R.attr#windowLightNavigationBar) style attribute is not available on `O` (it can only be applied programmatically on API 26).

## Changelog:

[ANDROID] [ADDED] - Add navigationBarTranslucent prop to Modal component

Pull Request resolved: https://github.com/facebook/react-native/pull/47254

Test Plan:
Run the tester app, toggle `navigationBarTranslucent`:

https://github.com/user-attachments/assets/286d173b-35a5-4951-9105-f9f7562d6764

-----
did some additional testing with RNTester using different justification

|flex-start|flex-end|
|https://pxl.cl/5Rd20|https://pxl.cl/5Rd21|

Reviewed By: javache

Differential Revision: D65103501

Pulled By: alanleedev

fbshipit-source-id: ef6473ecd785976d3e26c77bbc212222ec96c9f2
2024-11-06 21:09:36 -08:00
Mathieu ActhernoeneandFacebook GitHub Bot 33e0521788 Add view getter on RCTRootView / RCTFabricSurfaceHostingProxyRootView (#37310)
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
2023-05-10 05:48:17 -07:00
Mathieu ActhernoeneandFacebook Github Bot eebfd33b70 Expose StatusBar height on iOS
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
2017-01-23 12:58:34 -08:00