Skip to content

Commit c460fb7

Browse files
alduzykkafar
andauthored
fix(iOS): fullscreenmodal color scheme adaptability (#2211)
## Description This PR fixes the color scheme adaptability when using `presentation: fullScreenModal`. When changing the appearance mode between `light` and `dark` the screens reacted immediately except for the fullScreenModal presentation style. When using a `UIModalPresentationFullScreen` the views belonging to the presenting view controller are removed after the presentation completes. After investigating the view hierarchy for a screen with `presentation: fullScreenModal` it turned out that the `RCTRootView` is removed, thus the `traitCollectionDidChange` observer ([see here](https://github.com/facebook/react-native/blob/d3e0430deac573fd44792e6005d5de20e9ad2797/packages/react-native/React/Base/RCTRootView.m#L362)) is not working anymore. The solution was to add an extra observer for `RNSScreenStackPresentationFullScreenModal` to be able to send proper notifications when no RCTRootView is present. As the observer is working synchronously it's usage is limited for this presentation style only. Fixes #2002. ## Changes - added repro `Test2002.tsx` - added `traitCollectionDidChange` observer for fullScreenModal ## Screenshots / GIFs ### Before https://github.com/software-mansion/react-native-screens/assets/91994767/52fa4e92-3baa-49e2-b278-7be57c4d28b3 ### After https://github.com/software-mansion/react-native-screens/assets/91994767/74c62c45-c793-4f63-81fc-d68d4000fea6 ## Test code and steps to reproduce - added `Test2002.tsx` to test examples ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: <!-- For adding new props to native-stack --> - [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [ ] Ensured that CI passes --------- Co-authored-by: Kacper Kafara <[email protected]> Co-authored-by: Kacper Kafara <[email protected]>
1 parent da9b362 commit c460fb7

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

apps/test-examples/App.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import Test1844 from './src/Test1844';
9696
import Test1864 from './src/Test1864';
9797
import Test1970 from './src/Test1970';
9898
import Test1981 from './src/Test1981';
99+
import Test2002 from './src/Test2002';
99100
import Test2008 from './src/Test2008';
100101
import Test2028 from './src/Test2028';
101102
import Test2048 from './src/Test2048';
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import * as React from 'react';
2+
import { View, Button, useColorScheme, StyleSheet } from 'react-native';
3+
import {
4+
DarkTheme,
5+
DefaultTheme,
6+
NavigationContainer,
7+
} from '@react-navigation/native';
8+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
9+
10+
function HomeScreen({ navigation }) {
11+
return (
12+
<View style={styles.container}>
13+
<Button
14+
onPress={() => navigation.navigate('fullScreenModal')}
15+
title="Open fullScreenModal"
16+
/>
17+
<Button
18+
onPress={() => navigation.navigate('formSheet')}
19+
title="Open formSheet"
20+
/>
21+
</View>
22+
);
23+
}
24+
25+
function ModalScreen({ navigation }) {
26+
return (
27+
<View style={styles.container}>
28+
<Button onPress={() => navigation.goBack()} title="Dismiss" />
29+
</View>
30+
);
31+
}
32+
33+
const RootStack = createNativeStackNavigator();
34+
35+
export default function App() {
36+
const scheme = useColorScheme();
37+
38+
return (
39+
<NavigationContainer theme={scheme === 'dark' ? DarkTheme : DefaultTheme}>
40+
<RootStack.Navigator>
41+
<RootStack.Screen name="Home" component={HomeScreen} />
42+
<RootStack.Screen
43+
name="formSheet"
44+
component={ModalScreen}
45+
options={{ presentation: 'formSheet' }}
46+
/>
47+
<RootStack.Screen
48+
name="fullScreenModal"
49+
component={ModalScreen}
50+
options={{ presentation: 'fullScreenModal' }}
51+
/>
52+
</RootStack.Navigator>
53+
</NavigationContainer>
54+
);
55+
}
56+
57+
const styles = StyleSheet.create({
58+
container: { flex: 1, alignItems: 'center', justifyContent: 'center' },
59+
});

ios/RNSModalScreen.mm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,28 @@
77

88
@implementation RNSModalScreen
99

10+
// When using UIModalPresentationStyleFullScreen the whole view hierarchy mounted under primary `UITransitionView` is
11+
// removed, including React's root view, which observes for trait collection changes & sends it to `Appearance` module
12+
// via system notification centre. To workaround this detached-root-view-situation we emit the event to React's
13+
// `Appearance` module ourselves. For the RCTRootView observer, visit
14+
// https://github.com/facebook/react-native/blob/d3e0430deac573fd44792e6005d5de20e9ad2797/packages/react-native/React/Base/RCTRootView.m#L362
15+
// For more information, see https://github.com/software-mansion/react-native-screens/pull/2211.
16+
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
17+
{
18+
[super traitCollectionDidChange:previousTraitCollection];
19+
if (RCTSharedApplication().applicationState == UIApplicationStateBackground ||
20+
self.stackPresentation != RNSScreenStackPresentationFullScreenModal) {
21+
return;
22+
}
23+
24+
[[NSNotificationCenter defaultCenter]
25+
postNotificationName:RCTUserInterfaceStyleDidChangeNotification
26+
object:self
27+
userInfo:@{
28+
RCTUserInterfaceStyleDidChangeNotificationTraitCollectionKey : self.traitCollection,
29+
}];
30+
}
31+
1032
#ifdef RCT_NEW_ARCH_ENABLED
1133
+ (react::ComponentDescriptorProvider)componentDescriptorProvider
1234
{

0 commit comments

Comments
 (0)