12

I am experiencing this when transitioning to one screen to another with two different navigators: ex-navigation and the new one React Navigation . There is a white flickering for a second (or half a second). Looking for a solution I found that other navigators have the same problem. For example the navigator from wix HERE. From the link:

Ok, the problem is, that React styles applies after the navigation started, and by default the backgroundColor is white, so this is the flicker effect..

Someone having the same issue?

Shan
  • 948
  • 1
  • 9
  • 17
vaklinzi
  • 1,913
  • 2
  • 18
  • 30
  • 1
    Solved with: https://medium.com/@Krizzu/how-to-change-background-color-of-rootview-in-react-native-3279417c34bb My TabNavigator was giving me a white flash before mounting my screens. – Jordan Grant Sep 01 '19 at 23:54

10 Answers10

18

I resolved the white flickering issue by setting the property in NavigationContainer of React-Navigation v5.

<NavigationContainer theme={{ colors: { background: '#000' } }}>
{...}
</NavigationContainer>

It helped me remove white flickering as I updated the color same as my background color BLACK.

https://github.com/software-mansion/react-native-screens/issues/380#issuecomment-748038449

Ubaid
  • 737
  • 8
  • 18
3

For me this did the trick:

cardStyle: { opacity: 1 }

Example:

const RootNavigator = createStackNavigator({
    Login: { screen: Login },
    Main: { screen: DrawerNavigator }
},
    {
        initialRouteName: 'Login',
        cardStyle: { opacity: 1 } // Prevent white flicker on Android when navigating between screens
    }
);

export default createAppContainer(RootNavigator);
Dror Bar
  • 686
  • 2
  • 10
  • 19
2

I know that I am posting way late here, but yeah if someone get help by this then it'll be worth it.

I also faced the same issue because I was using dark theme for my project and whenever the navigation happened a white screen flashed for some milliseconds.

I resolved this issue by adding the same theme background color to NavigationContainer theme prop like below

<NavigationContainer theme ={{colors:{background: /*same background color of your project */}}}> .... </NavigationContainer>

This solved my issue, hope it solves other's too.

Thank You..

1

When use DrawerNavigator and StackNavigator, need:

cardStyle: {
    backgroundColor: 'transparent',
},

and need:

use react-native-root-view-background to setRootViewBackgroundColor('black')

Li Zheng
  • 685
  • 7
  • 11
1

For people using expo, you also need to pass a backgroundColor in your app.json. So you should set this to some dark color from your app's color scheme.

// app.json

{
  "expo": {
    ...
    "backgroundColor": "#1a202c"
  }
}
Divyanshu Maithani
  • 13,908
  • 2
  • 36
  • 47
1

I've created a Typescript cardStyleInterpolator function based on scaleFromAndroid to prevent the whitespace around the screen when switching the screens.

This function removes the opacity: 0 and the end of transition and adds a overlayStyle to the border of the screen while switching beetween the screens.

Example:

<Stack.Navigator
  screenOptions={{
    headerShown: false, /* Hide the header */
    cardStyleInterpolator: scaleCenterAndroidInterpolator /* Overrides the default cardStyleInterpolator */
  }}>
  ...
</Stack.Navigator>

    const scaleCenterAndroidInterpolator = ({ 
        current, 
        closing, 
        next 
    }: StackCardInterpolationProps)  => {

        const { add, multiply } = Animated;

        const handleConditionalScale = (
            condition: Animated.AnimatedInterpolation, 
            main: Animated.AnimatedInterpolation, 
            fallback: Animated.AnimatedInterpolation) => (
                add(multiply(condition, main), multiply(condition.interpolate({
                    inputRange: [0, 1],
                    outputRange: [1, 0]
                  }), fallback))
            )

        const progress: Animated.AnimatedAddition = add(current.progress.interpolate({
            inputRange: [0, 1],
            outputRange: [0, 1],
            extrapolate: 'clamp'
          }), next ? next.progress.interpolate({
            inputRange: [0, 1],
            outputRange: [0, 1],
            extrapolate: 'clamp'
          }) : 0);

        const opacity: Animated.AnimatedInterpolation = progress.interpolate({
            inputRange: [0, 0.75, 0.875, 1, 1.0825, 1.2075, 2],
            outputRange: [0, 0, 1, 1, 1, 1, 1]
        });

        const scale: Animated.AnimatedAddition = handleConditionalScale(closing, current.progress.interpolate({
            inputRange: [0, 1],
            outputRange: [0.925, 1],
            extrapolate: 'clamp'
          }), progress.interpolate({
            inputRange: [0, 1, 2],
            outputRange: [0.85, 1, 1.075]
          }));

        const overlayStyle: { opacity: Animated.AnimatedInterpolation } = {
            opacity: current.progress.interpolate({
                inputRange: [0, 1],
                outputRange: [0, 0.5],
                extrapolate: 'clamp',
            })
        }

        return {
            cardStyle: {
                opacity: opacity,
                transform: [
                    { scale }
                ],
            },
            overlayStyle
        }

    }
0

I have had the same problem. And it seems to me that there are two solutions to that.

  • First solution comes from the link you share. Basically you can add a background color to your Navigator component.
  • Second solution, which I applied to my project previously, is not an exact one but a workaround. I changed how Navigator component transitions screens back and forth by changing SceneConfigs, from Navigator.SceneConfigs.FloatFromRight to Navigator.SceneConfigs.PushFromRight. So my Navigator component become something like;

            <Navigator
                ref={(ref) => this._navigator = ref}
                configureScene={(route) => {
                    return {
                        ...Navigator.SceneConfigs.PushFromRight,
                        gestures: {}
                    };
                }}
                initialRoute={{
                    id: (Platform.OS === "android" || Platform.OS === "ios") ? 'splashscreen' : 'login',
                    statusBarHidden: true
                }}
                renderScene={this.renderScene}
            />
    
milkersarac
  • 3,399
  • 3
  • 31
  • 31
0

You can set background color in your navigator like this:

<
Navigator style={{flex: 1}} 
  transitionerStyle={{backgroundColor: 'black'}} ...

Hope this helps-

Abhay Dixit
  • 998
  • 8
  • 28
0

For me the solution was setting the layout option. I am using wix-react-native-navigation:

    layout: {
      backgroundColor: "#000",
      componentBackgroundColor: "#000",
    },
Milan Rakos
  • 1,705
  • 17
  • 24
0

None of the above answers worked for me. For iOS, I changed the background color in AppDelegate.m

if (@available(iOS 13.0, *)) {
rootView.backgroundColor = [UIColor blackColor]; ---> changed this
} else {
rootView.backgroundColor = [UIColor blackColor]; ---> and this
}

For android: (It's not perfect, black screen is shown for a while after splash srceen. My theme was dark so, it was good to go.) In MainActivity.java,

@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.show(this, true); ---> added true here
super.onCreate(savedInstanceState);
}

In styles.xml,

<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="windowNoTitle">true</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
    <item name="windowActionBar">false</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:backgroundDimEnabled">false</item>
    <item name="android:windowDisablePreview">true</item>
</style>