Skip to content

Commit 36ffc4f

Browse files
spencercarlikelset
authored andcommitted
[iOS 11] Handle landscape tabbar correctly. (react-navigation#2676)
* Handle the ios11 tabbar correctly * Fix an issue when showLabel is false * Add a basic test for the tabbarbottom * Add check for ios version number * Tests shall pass * make things work for all the versions * Again, fix the tests
1 parent 82c2cdb commit 36ffc4f

File tree

3 files changed

+307
-12
lines changed

3 files changed

+307
-12
lines changed

src/views/TabView/TabBarBottom.js

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
/* @flow */
22

33
import React, { PureComponent } from 'react';
4-
import { Animated, TouchableWithoutFeedback, StyleSheet } from 'react-native';
4+
import {
5+
Animated,
6+
TouchableWithoutFeedback,
7+
StyleSheet,
8+
View,
9+
Platform,
10+
} from 'react-native';
511
import TabBarIcon from './TabBarIcon';
12+
import withOrientation from '../withOrientation';
613

714
import type {
815
NavigationAction,
@@ -45,13 +52,13 @@ type Props = {
4552
style?: ViewStyleProp,
4653
labelStyle?: TextStyleProp,
4754
tabStyle?: ViewStyleProp,
55+
showIcon?: boolean,
56+
isLandscape?: boolean,
4857
};
4958

50-
export default class TabBarBottom extends PureComponent<
51-
DefaultProps,
52-
Props,
53-
void
54-
> {
59+
const majorVersionIOS = parseInt(Platform.Version, 10);
60+
61+
class TabBarBottom extends PureComponent<DefaultProps, Props, void> {
5562
// See https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/UIKitUICatalog/UITabBar.html
5663
static defaultProps: DefaultProps = {
5764
activeTintColor: '#3478f6', // Default active tint color in iOS 10
@@ -73,6 +80,8 @@ export default class TabBarBottom extends PureComponent<
7380
inactiveTintColor,
7481
labelStyle,
7582
showLabel,
83+
showIcon,
84+
isLandscape,
7685
allowFontScaling,
7786
} = this.props;
7887
if (showLabel === false) {
@@ -93,10 +102,19 @@ export default class TabBarBottom extends PureComponent<
93102

94103
const tintColor = scene.focused ? activeTintColor : inactiveTintColor;
95104
const label = this.props.getLabel({ ...scene, tintColor });
105+
let marginLeft = 0;
106+
if (isLandscape && showIcon && majorVersionIOS >= 11) {
107+
marginLeft = LABEL_LEFT_MARGIN;
108+
}
109+
let marginTop = 0;
110+
if (!isLandscape && showIcon && majorVersionIOS >= 11) {
111+
marginTop = LABEL_TOP_MARGIN;
112+
}
113+
96114
if (typeof label === 'string') {
97115
return (
98116
<Animated.Text
99-
style={[styles.label, { color }, labelStyle]}
117+
style={[styles.label, { color, marginLeft, marginTop }, labelStyle]}
100118
allowFontScaling={allowFontScaling}
101119
>
102120
{label}
@@ -119,6 +137,7 @@ export default class TabBarBottom extends PureComponent<
119137
inactiveTintColor,
120138
renderIcon,
121139
showIcon,
140+
showLabel,
122141
} = this.props;
123142
if (showIcon === false) {
124143
return null;
@@ -131,7 +150,7 @@ export default class TabBarBottom extends PureComponent<
131150
inactiveTintColor={inactiveTintColor}
132151
renderIcon={renderIcon}
133152
scene={scene}
134-
style={styles.icon}
153+
style={showLabel && majorVersionIOS >= 11 ? {} : styles.icon}
135154
/>
136155
);
137156
};
@@ -153,6 +172,7 @@ export default class TabBarBottom extends PureComponent<
153172
inactiveBackgroundColor,
154173
style,
155174
tabStyle,
175+
isLandscape,
156176
} = this.props;
157177
const { routes } = navigation.state;
158178
// Prepend '-1', so there are always at least 2 items in inputRange
@@ -173,9 +193,11 @@ export default class TabBarBottom extends PureComponent<
173193
inputRange,
174194
outputRange: (outputRange: Array<string>),
175195
});
196+
176197
const justifyContent = this.props.showIcon ? 'flex-end' : 'center';
177198
const extraProps = this._renderTestIDProps(scene) || {};
178199
const { testID, accessibilityLabel } = extraProps;
200+
179201
return (
180202
<TouchableWithoutFeedback
181203
key={route.key}
@@ -187,7 +209,9 @@ export default class TabBarBottom extends PureComponent<
187209
<Animated.View
188210
style={[
189211
styles.tab,
190-
{ backgroundColor, justifyContent },
212+
isLandscape && majorVersionIOS >= 11 && styles.tabLandscape,
213+
!isLandscape && majorVersionIOS >= 11 && styles.tabPortrait,
214+
{ backgroundColor },
191215
tabStyle,
192216
]}
193217
>
@@ -202,18 +226,28 @@ export default class TabBarBottom extends PureComponent<
202226
}
203227
}
204228

229+
const LABEL_LEFT_MARGIN = 20;
230+
const LABEL_TOP_MARGIN = 15;
205231
const styles = StyleSheet.create({
206232
tabBar: {
207-
height: 49, // Default tab bar height in iOS 10
233+
height: 49, // Default tab bar height in iOS 10+
208234
flexDirection: 'row',
209235
borderTopWidth: StyleSheet.hairlineWidth,
210236
borderTopColor: 'rgba(0, 0, 0, .3)',
211-
backgroundColor: '#F7F7F7', // Default background color in iOS 10
237+
backgroundColor: '#F7F7F7', // Default background color in iOS 10+
212238
},
213239
tab: {
214240
flex: 1,
215-
alignItems: 'stretch',
241+
alignItems: 'center',
242+
justifyContent: 'flex-end',
243+
},
244+
tabPortrait: {
216245
justifyContent: 'flex-end',
246+
flexDirection: 'column',
247+
},
248+
tabLandscape: {
249+
justifyContent: 'center',
250+
flexDirection: 'row',
217251
},
218252
icon: {
219253
flexGrow: 1,
@@ -225,3 +259,5 @@ const styles = StyleSheet.create({
225259
backgroundColor: 'transparent',
226260
},
227261
});
262+
263+
export default withOrientation(TabBarBottom);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react';
2+
import { View } from 'react-native';
3+
import renderer from 'react-test-renderer';
4+
import TabRouter from '../../routers/TabRouter';
5+
6+
import TabView from '../TabView/TabView';
7+
import TabBarBottom from '../TabView/TabBarBottom';
8+
9+
describe('TabBarBottom', () => {
10+
it('renders successfully', () => {
11+
const navigation = {
12+
state: {
13+
index: 0,
14+
routes: [{ key: 's1', routeName: 's1' }],
15+
},
16+
};
17+
const router = TabRouter({ s1: { screen: View } });
18+
19+
const rendered = renderer
20+
.create(
21+
<TabView
22+
tabBarComponent={TabBarBottom}
23+
navigation={navigation}
24+
router={router}
25+
/>
26+
)
27+
.toJSON();
28+
29+
expect(rendered).toMatchSnapshot();
30+
});
31+
});

0 commit comments

Comments
 (0)