Skip to content

Commit eedb311

Browse files
authored
feat(iOS, SplitView): Add support for orientation on SplitViewHost (#3106)
## Description Closes: software-mansion/react-native-screens-labs#335 Adding support for orientation prop on SplitViewHost. Note: Due to the issue with interoperability between Swift and Objective-C, the RNSOrientation enum and RNSOrientationProviding protocol are duplicated with the Objective-C definitions. We should investigate this further, as it seems to be a common problem in the future. ## Changes - Updated JS APIs covering the orientation prop - Updated appearance coordinator, component and controller for SplitView host. - Added definitions for enum and protocol on the swift side. ## Screenshots / GIFs Note: the difference between 18 and 26 is intentional: software-mansion/react-native-screens-labs#347 (comment) iOS 18 <img width="578" height="754" alt="Screenshot 2025-08-08 at 09 51 28" src="https://github.com/user-attachments/assets/780c153e-43cd-4998-ba7e-bdeb9900529c" /> iOS 26 <img width="586" height="763" alt="Screenshot 2025-08-07 at 16 01 27" src="https://github.com/user-attachments/assets/9b98df8d-84f9-4874-a250-5ce9746d7ef8" /> ## Test code and steps to reproduce Added a new example for testing orientation. ## Checklist - [x] Included code example that can be used to test this change - [x] Ensured that CI passes
1 parent 492efd6 commit eedb311

15 files changed

+235
-1
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import React from 'react';
2+
import { StyleSheet, Text, View } from 'react-native';
3+
import { SplitViewHost, SplitViewScreen } from 'react-native-screens';
4+
import { Colors } from '../../shared/styling/Colors';
5+
import { SplitViewBaseConfig } from './helpers/types';
6+
7+
const SplitViewOrientation = ({ splitViewBaseConfig }: { splitViewBaseConfig: SplitViewBaseConfig }) => {
8+
return (
9+
<SplitViewHost {...splitViewBaseConfig} orientation='landscapeLeft'>
10+
<SplitViewScreen.Column>
11+
<View style={[styles.container, { backgroundColor: Colors.White }]}>
12+
<Text style={styles.text}>Primary column</Text>
13+
</View>
14+
</SplitViewScreen.Column>
15+
<SplitViewScreen.Column>
16+
<View style={[styles.container, { backgroundColor: Colors.White }]}>
17+
<Text style={styles.text}>Supplementary column</Text>
18+
</View>
19+
</SplitViewScreen.Column>
20+
<SplitViewScreen.Column>
21+
<View style={[styles.container, { backgroundColor: Colors.White }]}>
22+
<Text style={styles.text}>Secondary column</Text>
23+
</View>
24+
</SplitViewScreen.Column>
25+
</SplitViewHost>
26+
);
27+
}
28+
29+
const styles = StyleSheet.create({
30+
wrapper: {
31+
flex: 1,
32+
},
33+
container: {
34+
flex: 1,
35+
width: '100%',
36+
height: '100%',
37+
alignItems: 'center',
38+
justifyContent: 'center'
39+
},
40+
text: {
41+
fontSize: 24
42+
},
43+
button: {
44+
width: 120,
45+
height: 40,
46+
justifyContent: 'center',
47+
alignItems: 'center',
48+
backgroundColor: Colors.BlueDark100
49+
}
50+
})
51+
52+
export default SplitViewOrientation;

apps/src/tests/TestSplitView/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22

33
import SplitViewBaseApp from './SplitViewBaseApp';
4+
import SplitViewOrientation from './SplitViewOrientation';
45
import {
56
SplitViewWithNestedStack,
67
SplitViewWithNativeStackBase,

ios/RNSEnums.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ typedef NS_ENUM(NSInteger, RNSTabBarMinimizeBehavior) {
141141
};
142142
#endif
143143

144+
// TODO: investigate objc - swift interop and deduplicate this code
145+
// This enum needs to be compatible with the RNSOrientationSwift enum.
144146
typedef NS_ENUM(NSInteger, RNSOrientation) {
145147
RNSOrientationInherit,
146148
RNSOrientationAll,

ios/RNSOrientationProviding.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
NS_ASSUME_NONNULL_BEGIN
44

5+
// TODO: investigate objc - swift interop and deduplicate this code
6+
// This class needs to be compatible with the RNSOrientationProvidingSwift.
57
@protocol RNSOrientationProviding
68

79
- (RNSOrientation)evaluateOrientation;

ios/conversion/RNSConversions-SplitView.mm

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,35 @@ UISplitViewControllerDisplayModeButtonVisibility SplitViewDisplayModeButtonVisib
9797
}
9898
}
9999

100+
RNSOrientation RNSOrientationFromRNSSplitViewHostOrientation(react::RNSSplitViewHostOrientation orientation)
101+
{
102+
using enum facebook::react::RNSSplitViewHostOrientation;
103+
104+
switch (orientation) {
105+
case Inherit:
106+
return RNSOrientationInherit;
107+
case All:
108+
return RNSOrientationAll;
109+
case AllButUpsideDown:
110+
return RNSOrientationAllButUpsideDown;
111+
case Portrait:
112+
return RNSOrientationPortrait;
113+
case PortraitUp:
114+
return RNSOrientationPortraitUp;
115+
case PortraitDown:
116+
return RNSOrientationPortraitDown;
117+
case Landscape:
118+
return RNSOrientationLandscape;
119+
case LandscapeLeft:
120+
return RNSOrientationLandscapeLeft;
121+
case LandscapeRight:
122+
return RNSOrientationLandscapeRight;
123+
default:
124+
RCTLogError(@"[RNScreens] unsupported orientation");
125+
return RNSOrientationInherit;
126+
}
127+
}
128+
100129
#pragma mark SplitViewScreen props
101130

102131
RNSSplitViewScreenColumnType RNSSplitViewScreenColumnTypeFromScreenProp(

ios/conversion/RNSConversions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ SplitViewDisplayModeButtonVisibilityFromHostProp(
8585
std::string UISplitViewControllerDisplayModeToString(
8686
UISplitViewControllerDisplayMode displayMode);
8787

88+
RNSOrientation RNSOrientationFromRNSSplitViewHostOrientation(
89+
react::RNSSplitViewHostOrientation orientation);
90+
8891
#pragma mark SplitViewScreen props
8992

9093
RNSSplitViewScreenColumnType RNSSplitViewScreenColumnTypeFromScreenProp(
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// TODO: investigate objc - swift interop and deduplicate this code
2+
// This class needs to follow the RNSOrientationProviding from objc.
3+
@objc
4+
public protocol RNSOrientationProvidingSwift {
5+
func evaluateOrientation() -> RNSOrientationSwift
6+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// TODO: investigate objc - swift interop and deduplicate this code
2+
// This enum needs to follow the RNSOrientation from objc.
3+
@objc
4+
public enum RNSOrientationSwift: Int {
5+
case inherit
6+
case all
7+
case allButUpsideDown
8+
case portrait
9+
case portraitUp
10+
case portraitDown
11+
case landscape
12+
case landscapeLeft
13+
case landscapeRight
14+
}

ios/gamma/split-view/RNSSplitViewAppearanceApplicator.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class RNSSplitViewAppearanceApplicator {
4444

4545
self.updateSplitViewDisplayMode(for: splitView, withController: splitViewController)
4646
}
47+
48+
appearanceCoordinator.updateIfNeeded(.orientationUpdate) { [] in
49+
RNSScreenWindowTraits.enforceDesiredDeviceOrientation()
50+
}
4751
}
4852

4953
///

ios/gamma/split-view/RNSSplitViewAppearanceUpdateFlags.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ struct RNSSplitViewAppearanceUpdateFlags: OptionSet {
77
static let generalUpdate = RNSSplitViewAppearanceUpdateFlags(rawValue: 1 << 0)
88
static let secondaryScreenNavBarUpdate = RNSSplitViewAppearanceUpdateFlags(rawValue: 1 << 1)
99
static let displayModeUpdate = RNSSplitViewAppearanceUpdateFlags(rawValue: 1 << 2)
10+
static let orientationUpdate = RNSSplitViewAppearanceUpdateFlags(rawValue: 1 << 3)
1011
}

0 commit comments

Comments
 (0)