Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SafeAreaView not working with MaterialTopTabNavigator at root

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.

like image 545
Phobos Avatar asked Apr 15 '19 17:04

Phobos


2 Answers

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,
  }
);
like image 67
brentvatne Avatar answered Jan 24 '23 21:01

brentvatne


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.

like image 20
Phobos Avatar answered Jan 24 '23 20:01

Phobos