We use MaterialTopTabNavigator
(https://reactnavigation.org/docs/en/material-top-tab-navigator.html) at the root of our application. According to the react-navigation documentation, there should be a SafeAreaView applied to the TabNavigator by default.
It only seems to be getting the inset applied to the top of the screen, and as a result (or so I can only assume), there is no padding being applied to the bottom which causes phones such as the iPhoneX and other larger devices to have overlap.
According to the React-Navigation documentation, there should be a tabBarOptions
config which allows you to override the forceInset
prop of the SafeAreaView
(safeAreaInset
). However, having ensured that we have the latest react-navigation package installed, the safeAreaInset
is nowhere to be found.
Is there a way to apply the inset directly to the MaterialTopTabNavigator
?
Our MainNavigator looks as follows:
const MainNavigator = createMaterialTopTabNavigator(
{
Group: {
screen: GroupStack,
navigationOptions: {
tabBarIcon: () => (
<Icon name={'group-work'} color={'#FFF'}/>
),
},
},
Stats: {
screen: StatisticsStack,
navigationOptions: {
tabBarIcon: () => (
<Icon name={'insert-chart'} color={'#FFF'}/>
),
},
},
GroupRoundsTab: {
screen: GroupRoundStack,
navigationOptions: {
tabBarIcon: () => (
<Icon name={'group'} color={'#FFF'}/>
),
tabBarLabel: 'Rounds',
},
},
MoreTab: {
screen: MoreStack,
navigationOptions: {
tabBarIcon: () => (
<Icon name={'more-vert'} color={'#FFF'}/>
),
tabBarLabel: 'More',
},
},
}, {
tabBarPosition: 'bottom',
animationEnabled: false,
swipeEnabled: false,
lazy: true,
tabBarOptions: {
upperCaseLabel: false,
labelStyle: {
fontSize: 10,
margin: 0,
},
indicatorStyle: {
backgroundColor: '#FFF',
},
style: {
backgroundColor: PRIMARY_COLOUR,
},
tabStyle: {
height: 50,
alignItems: 'center',
justifyContent: 'center',
},
showIcon: true,
},
});
The only solution we have found is to wrap our entire application in a SafeAreaView
as follows:
<StatusBar barStyle="dark-content"/>
<SafeAreaView style={{ flex: 1 }}>
<AppContainer/>
<OfflineNotice/>
</SafeAreaView>
The huge downside here is that any StackNavigators within the main TabNavigation get double padding because react-navigation is auto applying the SafeAreaView
on these screens again.
You can add a SafeAreaView wrapper around the top tab view like this:
import {
MaterialTopTabBar,
SafeAreaView,
createAppContainer,
createMaterialTopTabNavigator,
} from 'react-navigation';
class MaterialTopTabBarWrapper extends React.Component {
render() {
return (
<SafeAreaView
style={{ backgroundColor: '#2196f3' }}
forceInset={{ top: 'always', horizontal: 'never', bottom: 'never' }}>
<MaterialTopTabBar {...this.props} />
</SafeAreaView>
);
}
}
let Tabs = createMaterialTopTabNavigator(
{
/* your routes */
},
{
tabBarComponent: MaterialTopTabBarWrapper,
}
);
I chose not to hack the original navigator too much. Instead of adding extra complexity, I simply added the following default navigation properties to each of the StackNavigator
routes to ensure that they didn't add extra padding as a result of being rendered within the original SafeAreaView
.
defaultNavigationOptions: {
headerForceInset: {
top: 'never',
bottom: 'never',
},
},
This ensures that all inner screens and outer screens are correctly padded. Not an ideal solution, but at least it is easy to adjust if changes need to be made down the line.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With