21

I have a single application which includes only navigation packages. On IOS, all is fine but on Android, header and/or bottom tabbar seems like jumping (maybe recalculating their positions). This happens only when I use navigation components and only when app is just launched. Is there anyone faced same problem?

enter image description here

Thanks in advance.


Packages:

"@react-native-community/masked-view": "^0.1.10",
"@react-navigation/bottom-tabs": "^5.6.1",
"@react-navigation/native": "^5.6.1",
"@react-navigation/stack": "^5.6.2",
"react": "16.11.0",
"react-native": "0.62.2",
"react-native-gesture-handler": "^1.6.1",
"react-native-reanimated": "^1.9.0",
"react-native-safe-area-context": "^3.0.7",
"react-native-screens": "^2.9.0"

This is the whole app:

import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

function DetailsScreen() {
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Details!</Text>
        </View>
    );
}

function HomeScreen({ navigation }) {
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Home screen</Text>
            <Button
                title="Go to Details"
                onPress={() => navigation.navigate('Details')}
            />
        </View>
    );
}

function SettingsScreen({ navigation }) {
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Settings screen</Text>
            <Button
                title="Go to Details"
                onPress={() => navigation.navigate('Details')}
            />
        </View>
    );
}

const HomeStack = createStackNavigator();

function HomeStackScreen() {
    return (
        <HomeStack.Navigator>
            <HomeStack.Screen name="Home" component={HomeScreen} />
            <HomeStack.Screen name="Details" component={DetailsScreen} />
        </HomeStack.Navigator>
    );
}

const SettingsStack = createStackNavigator();

function SettingsStackScreen() {
    return (
        <SettingsStack.Navigator>
            <SettingsStack.Screen name="Settings" component={SettingsScreen} />
            <SettingsStack.Screen name="Details" component={DetailsScreen} />
        </SettingsStack.Navigator>
    );
}

const Tab = createBottomTabNavigator();

export default function App() {
    return (
        <NavigationContainer>
            <Tab.Navigator>
                <Tab.Screen name="Home" component={HomeStackScreen} />
                <Tab.Screen name="Settings" component={SettingsStackScreen} />
            </Tab.Navigator>
        </NavigationContainer>
    );
}
Basar Sen
  • 349
  • 3
  • 12
  • Hello @Basar Sen, Can you try it with the RN 0.61.5 version? It should not be jumping like that. Also, please try it on a real device. – FreakyCoder Jul 03 '20 at 10:29
  • @FreakyCoder Thank you. I tried you suggestion. But it's still same. That's a weird bug :) – Basar Sen Jul 03 '20 at 12:37
  • Let me test it :) – FreakyCoder Jul 03 '20 at 13:14
  • 1
    @FreakyCoder I tried with this combination. Now it works properly :). "react": "16.11.0", "react-native": "0.62.2", "@react-navigation/bottom-tabs": "^5.2.5", "@react-navigation/native": "^5.1.4", "@react-navigation/stack": "^5.2.9", "@react-native-community/masked-view": "^0.1.7", "react-native-gesture-handler": "^1.6.1", "react-native-reanimated": "^1.7.1", "react-native-screens": "^2.4.0", "react-native-safe-area-context": "^0.7.3" – Basar Sen Jul 03 '20 at 13:44
  • i get the same problem "@react-navigation/bottom-tabs": "^5.5.1", – ruandao Aug 23 '20 at 04:04
  • Hello Basar Sen, Did you find any solution to this problem? I am facing same problem. – Arun Girivasan Oct 09 '20 at 04:32
  • @ArunGirivasan did you find a solution ? – Stanly Medjo Mar 01 '21 at 17:24
  • @StanlyMedjoYes, please check the answer below. [https://stackoverflow.com/a/64274224/10505503](https://stackoverflow.com/a/64274224/10505503) – Arun Girivasan Mar 02 '21 at 03:56

4 Answers4

22

I fixed this problem by using SafeAreaProvider. You should add SafeAreaProvider in your app root component and use SafeAreaView as the root component of your page. Also check the import statement of SafeAreaView , react-native also has SafeAreaView but that component only supports iOS 10+ .

Arun Girivasan
  • 532
  • 1
  • 10
  • 24
  • I also needed to reset safeAreaInsets. Refer to my updated answer: https://stackoverflow.com/a/67922977/492325 – badsyntax Jun 10 '21 at 14:27
9

I was struggling with this exact bug for a while. I've finally been able to find a workaround.

It seems that all the ReactNavigation navigators (eg Tab and Stack) will by default accommodate safe areas. This is mentioned in this page: https://reactnavigation.org/docs/bottom-tab-navigator/

By default, the device's safe area insets are automatically detected

So it seems the behaviour we're seeing is due to this. It's not clear why ReactNavigation has buggy "safe area" logic, but the workaround is to disable that.

The workaround is similar to what @Arun Girivasan has suggested, with a couple extra steps:

  1. Use react-native-safe-area-context to wrap everything in a SafeAreaProvider and SafeAreaView
  2. Specify the safeAreaInsets to be 0 for all directions:
<Tab.Navigator
  initialRouteName="AppDashboard"
  tabBarOptions={{
    safeAreaInsets: {
      top: 0,
      bottom: 0,
      left: 0,
      right: 0,
    }
  }}
>
  1. If you're creating stacks within your tab screens, provide the same safeAreaInsets for your stack navigators.

With these changes I'm no longer seeing the tab bar height jump AND i'm no longer seeing the stack header jumping. Basically this workaround resolves all UI glitches for me.

badsyntax
  • 9,394
  • 3
  • 49
  • 67
  • Just saved me a bunch of time to solve this... – Miroslav Maksimovic Oct 18 '21 at 17:14
  • Just to works in the iOS and Android I put in the bottom prop a different value, using the lib `react-native-iphone-x-helper`i did it: `safeAreaInsets: { top: 0, bottom: getBottomSpace(), left: 0, right: 0 }` – Leonardo Leite Apr 06 '22 at 14:08
  • `Use react-native-safe-area-context to wrap everything in a SafeAreaProvider and SafeAreaView` fixed the issue. Thank you so much! – Ahmed Mahmoud Jun 01 '22 at 05:00
  • 1
    @badsyntax : After followed your instruction also, my bottom tabs jumping for the first time. Anyother possibilities for this issue? – Rotomac17 Jul 20 '22 at 05:58
1

same thing happend to me on @react-navigation/bottom-tabs i just removed paddingBottom and padding top from "tabstyle" and pasted in "style" this solved the issue

BEFORE:

  tabBarOptions={{
    keyboardHidesTabBar: true,
    activeTintColor: COLOR.white,

    style: {
      backgroundColor: COLOR.primary,
      height: responsiveHeight(7),
    },
    tabStyle: {
      paddingBottom: responsiveHeight(0.5),
      paddingTop: responsiveHeight(0.5),
    },
  }}

AFTER:

  tabBarOptions={{
    keyboardHidesTabBar: true,
    activeTintColor: COLOR.white,
    style: {
      backgroundColor: COLOR.primary,
      height: responsiveHeight(7),
      paddingBottom: responsiveHeight(0.5),
      paddingTop: responsiveHeight(0.5),
    },
  
  }}
...

i hope it helps :)

0

give this

navigationOptions: {
        headerShown: true,
        safeAreaInsets: {
          top: 0,
          bottom: 0,
          left: 0,
          right: 0,
        },
      },

if you are using react-navigation 4x

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Sagar
  • 51
  • 1
  • 1