React navigation V6 flashes white on slide between screen - react-native

I am using react navigation V6. And I have 6 components. But when I navigate from the first to the sixth: the transition goes through all the active components and flashes white. I would like to either remove the white flash or change the effect of the slide transition to fade. Thank you.
<View style={{flex: 1, borderTopWidth: 1, borderTopColor: '#5656582b'}}>
<Tab.Navigator
initialRouteName="Tous"
screenOptions={{
tabBarScrollEnabled: true,
tabBarIndicatorStyle: {
backgroundColor: '#60103b',
height: 4,
},
tabBarActiveTintColor: '#60103b',
tabBarInactiveTintColor: 'black',
tabBarLabelStyle: { fontSize: 17,color: 'black',fontWeight: "500",letterSpacing: 1},
tabBarItemStyle: {width: 'auto', padding: 10},
lazy:true,
swipeEnabled:false,
}
}
sceneAnimationEnabled = {false}
//animationEnabled: false}
>
<Tab.Screen name="Tous" initial component={Home} />
<Tab.Screen name="Livres" component={LivreHome} />
<Tab.Screen name="Livres Audios" component={LivreAudio} />
<Tab.Screen name="Podcasts" component={PodcastHome} />
<Tab.Screen name="Magasines" component={MagasineHome} />
<Tab.Screen name="Documents" component={DocumentHome} />
</Tab.Navigator>
</View>

First of all wrap <Tab.Navigator> in NavigationContainer
For remove white flash there is a way by giving dark theme to NavigationContainer
Example code
import {
NavigationContainer,
DarkTheme,
} from '#react-navigation/native';
export default () => {
return (
<NavigationContainer theme={DarkTheme}>
{/*Other Tab.Navigtor content*/}
</NavigationContainer>
);
};

<NavigationContainer theme={DarkTheme} >
{userDataSelect.hasOwnProperty('access_token')?
<MainNavigation /> : <AuthNavigation />
}
</NavigationContainer>
When I navigate on 2 successive screens, for example 1 to 2 or 2 to 3, there is no flash. But when I navigate from 1 to 5 I always have the white flash as if the navigation goes through all the components of the browser

Related

How to use Custom Fonts in Top Bar Navigation and Set Selected Tab Color

I am trying to create TopBar navigator (Which has already been created and works fine) and I want it to use Poppins as a font and then use this color #00BB23 for its selected tab bar for some reason, what i did does not seem to work as the screenshot is looking like this
My code is looking thus :
import {createMaterialTopTabNavigator} from '#react-navigation/material-top-tabs';
import LocalPayments from '../src/LocalPayments';
import InternationalPayments from '../src/InternationalPayments';
const Tab = createMaterialTopTabNavigator();
function TopNavigation() {
return (
<Tab.Navigator
initialRouteName="Local Payments"
tabBarOptions={{
activeTintColor: '#00BB23',
labelStyle: {fontSize: 12},
style: {backgroundColor: 'white'},
}}>
<Tab.Screen
name="Local Payments"
component={LocalPayments}
options={{tabBarLabel: 'Local Payments'}}
/>
<Tab.Screen
name="International Payments"
component={InternationalPayments}
options={{tabBarLabel: 'International Payments'}}
/>
</Tab.Navigator>
);
}
export default TopNavigation;
Please what do I do in this case?
I got it to work. Just some look ups on github / react native sources gave me an edge to what i wanted to see and get.
Code looks like this now
import {createMaterialTopTabNavigator} from '#react-navigation/material-top-tabs';
import LocalPayments from '../src/LocalPayments';
import InternationalPayments from '../src/InternationalPayments';
const Tab = createMaterialTopTabNavigator();
function TopNavigation() {
return (
<Tab.Navigator
initialRouteName="Local Payments"
screenOptions={{
tabBarPosition: 'top',
tabBarIndicatorStyle: {
backgroundColor: '#00BB23',
height : 3
},
tabBarLabelStyle: {
fontWeight: '240',
fontFamily: 'Poppins-Bold',
},
}}>
<Tab.Screen
name="Local Payments"
component={LocalPayments}
options={{tabBarLabel: 'Local Payments'}}
/>
<Tab.Screen
name="Intl. Payments"
component={InternationalPayments}
options={{tabBarLabel: 'Intl. Payments'}}
/>
</Tab.Navigator>
);
}
export default TopNavigation;
And the image looks thus :
So thanks everyone, hopefully it would help someone someday!

How to use modalPresentationStyle .fullscreen in React Native navigation

I am trying to create my first React Native application. I have a login screen from which I want to navigate to a register screen if users want to sign up.
To achieve this, I was thinking of opening a modal above the first screen (login). I created the following:
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
const Stack = createStackNavigator();
function RegisterScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ fontSize: 30 }}>Register Screen</Text>
<Button onPress={() => navigation.goBack()} title="Go back" />
</View>
);
}
function MyStack() {
return (
<Stack.Navigator>
<Stack.Group>
<Stack.Screen name="Login" component={LoginScreen} options={{ headerShown: false }} />
</Stack.Group>
<Stack.Group screenOptions={{ presentation: "modal", headerShown: false }} options={{modalPresentationStyle: 'fullScreen'}}>
<Stack.Screen name="Register" component={RegisterScreen} />
</Stack.Group>
</Stack.Navigator>
)
}
export default function App() {
return (
<NavigationContainer>
<MyStack />
</NavigationContainer>
);
}
This works perfectly fine, the modal shows. However, as you can see in this screenshot below, the modal is shown with modalPresentationStyle .automatic (in iOS). I want it to show as .fullScreen, so the hierarchy is not visible in the screen. Basically, I want the view to be shown from the safeArea/statusBar all the way down to the safeArea on the bottom.
How can I achieve this?
The terminology in React Native isn't the same as terminology in native apps. If you want a full-screen screen, you probably don't want a modal. If you want a vertical animation, change the animation based on docs:
screenOptions={{ cardStyleInterpolator: CardStyleInterpolators. forVerticalIOS, headerShown: false }}
https://reactnavigation.org/docs/stack-navigator/#animation-related-options
There's also no modalPresentationStyle: 'fullScreen' in documentation and Group component doesn't take an options prop.
The accepted answer states:
If you want a full-screen screen, you probably don't want a modal.
That's not necessarily true. Use
screenOptions={{ presentation: 'transparentModal' }}
or
screenOptions={{ presentation: 'fullScreenModal' }}
for a full screen modal animation you can't dismiss on iOS.

TouchableOpacity inside header is affected by view with absolute position in the screen on android

I have a Viewinside a SafeAreaView in a screen which has postion:absolute. When I include the view, a TouchableOpacity rendered in the header no longer responds in ANDROID (but always works fine in iOS).
Home screen:
render() {
return (
<SafeAreaView style={styles.SafeAreaContainer}>
<View style={styles.homeBackgroundContainer}> {/* <--- offending view! */}
<BlueCircle style={styles.homeBackgroundSvg} />
</View>
<View style={styles.homeView}>
<View style={styles.homeGreetingContainer}>
<Title style={styles.homeGreeting}>Hi, </Title>
<Title style={styles.homeGreetingName}>{username}</Title>
</View>
// Other components
</View>
</SafeAreaView>
);
}
styles.homeBackgroundContainer:
homeBackgroundContainer: {
borderColor: COLOR.transparent,
position: 'absolute',
top: '-50%',
left: '-25%',
right: 0,
bottom: 0,
},
The header is declared in the drawer navigator screen options. Note the TouchableOpacity in the header - this is used to open the drawer.
works in iOS
works from the "Content" screen
works when the homeBackgroundContainer(and its children) are commented out (Home Screen)
DOES NOT WORK IN ANDROID when homeBackgroundContainer is rendered (Home Screen).
Drawer Navigation & Header:
function DrawerContainer() {
return (
<Drawer.Navigator
screenOptions={({navigation}) => ({
headerLeft: titleLogo,
headerStyle: {
// colors only
},
headerTitle: () => {},
headerRight: () => (
<TouchableOpacity
style={styles.hamburgerIconButton}
onPress={() => navigation.toggleDrawer()}>
<Image source={require('../assets/hamburger.png')} />
</TouchableOpacity>
),
})}>
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{
headerShown: true,
// more options
}}
/>
<Drawer.Screen
name="Content"
component={ContentScreen}
options={{
headerShown: true,
}}
/>
</Drawer.Navigator>
);
}
styles.hamburgerIconButton:
hamburgerIconButton: {
marginRight: 20,
},
Other questions on SO have shown that absolute positioning can affect TouchableOpacity. I have tried setting the zIndex of the TouchableOpacity to 1, and also tried setting a positive elevation value but there is no change in behaviour.
Visually, I can see the header colors and content is rendered on top of the view which is the desired state. So if the header is rendered over the view, why isn't the TouchableOpacity responding?
To get the TouchableOpacityin a navigation header to respond on android when there's a view on the screen which has postion: absolute, I had to bring the headerStyle(not the touchable opacity style) forward on the z-axis.
screenOptions={() => ({
headerStyle: {
zIndex: 1,
},
})};

Change active border color from React Navigation - MaterialTopTabNavigator

There is a default blue bottom-border on the active tab. But I can't change this border-color.
Can somebody tell me how to change this default color ?
const Tab = createMaterialTopTabNavigator();
const SpecificChannelNavigator = () => (
<Tab.Navigator
tabBarOptions={{
style: {
// borderColor: colors['color-primary-500'],
borderColor: "transparant"
}
}}
>
<Tab.Screen name={Routes.groupChat} component={GroupChat} />
<Tab.Screen name={Routes.users} component={Users} />
<Tab.Screen name={Routes.groupChatSettings} component={ChannelSettings} />
</Tab.Navigator>
);
export default SpecificChannelNavigator;
You can use the indicatorStyle prop like this:
TabBarOptions={{
indicatorStyle:{backgroundColor: color}
}}

White background flashing when switching screens - React-Navigation v5

I'm migrating a RN project version 4 to 5.
When switching screens there was an issue with a white background flashing in.
In v4 this was solved by setting cardStyle: { backgroundColor: material.containerBgColor } in the StackNavigation options.
However in v5 I'm unable to fix it with the same approach:
<Stack.Navigator cardStyle={{ backgroundColor: material.containerBgColor }} ...>
White flash has come back. Any idea how to fix it? Thanks.
Update:
The structure of the navigation may be important:
const AppTabNavigator = () => (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Stack.Screen name="ScreenD" component={ScreenD} />
<Stack.Screen name="ScreenE" component={ScreenE} />
<Stack.Screen name="ScreenF" component={ScreenF} />
</Tab.Navigator>
)
...
<Stack.Navigator
...
cardStyle={{ backgroundColor: material.containerBgColor }}
>
<Stack.Screen name="Home" component={AppTabNavigator} />
<Stack.Screen name="ScreenA" component={ScreenA} />
<Stack.Screen name="ScreenB" component={ScreenB} />
<Stack.Screen name="ScreenC" component={ScreenC} />
</Stack.Navigator>
Going from ScreenD to ScreenE does the flashing issue. I'm not sure about the other screens as they don't make any network request / async stuff.
I faced the same issue and dived into an investigation. It seems that the detachment of the screens causes it. I found a few approaches. You can choose one according to your needs. They are the following:
You can specify a view wrapper of the navigator with the same background color as the screens one like:
<View style={{ flex: 1, backgroundColor: '#YOUR_SCREEN_COLOR' }}>
// It could be your NavigationContainer or your StackNavigator depends on your goals
<Navigator />
</View>
You can also specify your screen mode to be modal in the stack view config this prevents the screens from being detached like:
<StackNavigator.Navigator mode="modal">
{/*.... Your stack screens ... */}
</StackNavigator.Navigator>
You can add your custom overlay in screenOptions by using the cardOverlay prop:
cardOverlay: () => (
<View
style={{
flex: 1,
backgroundColor: '#YOUR_COLOR',
}}
/>)
Reference: https://reactnavigation.org/docs/stack-navigator/#cardoverlay
You can use the cardStyleInterpolator:
This allows you to customize the animation transitions when navigating from screen to screen.
Here are the snippets from the original documentation:
const forFade = ({ current, closing }) => ({
cardStyle: {
opacity: current.progress,
},
});
<Stack.Screen
name="Profile"
component={Profile}
options={{ cardStyleInterpolator: forFade }}
/>
Stack Navigator exposes various options to configure the transition animation when a screen is added or removed.
Reference: https://reactnavigation.org/docs/stack-navigator/#animation-related-options
Fixed it by using the DarkTheme for the Navigation Container
import { NavigationContainer, DarkTheme } from '#react-navigation/native';
return (
<NavigationContainer theme={DarkTheme}>
{children}
</NavigationContainer>
I am also using StackNavigator in v5, but none of the answers worked for me. That's how I solved the issue:
const navigatorOptions = {
headerShown: false,
cardStyle: { backgroundColor: 'transparent' },
cardStyleInterpolator: ({ current: { progress } }) => ({
cardStyle: {
opacity: progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
}),
},
overlayStyle: {
opacity: progress.interpolate({
inputRange: [0, 1],
outputRange: [0, 0.5],
extrapolate: 'clamp',
}),
},
}),
}
...
<AppStack.Navigator
screenOptions={navigatorOptions}
mode="modal"
>
...
I've found the solution here: https://reactnavigation.org/docs/stack-navigator#transparent-modals
An easy fix to this problem that worked for me is to set the sceneContainerStyle in the Tab Navigator like this:
<Tab.Navigator sceneContainerStyle={{backgroundColor: 'black'}}>
...//your screens here
</Tab.Navigator>
const App = () => (
<View style={styles.appStyle}>
<Navigation />
</View>
);
const styles = StyleSheet.create({
appStyle: { flex: 1, backgroundColor: "#000" }
});
Using react-native-navigation:^6.0.0, I tested everything here but actually the only things that work is to set a theme on the NavigationContainer
theme={{
colors: {
background: 'black',
},
}}
I used the solution provided by #jul
<SafeAreaProvider style={{ backgroundColor: "black" }}>
Small difference is that our SafeAreaProvider wraps NavigationContainer at a much higher level.
<SafeAreaProvider style={{ backgroundColor: "black" }}>
...
<NavigationContainer />
...
</SafeAreaProvider>
Serves as a default background color without using native modules to set the root background color
In my case it was due to the default styles of a SafeAreaProvider inside a NavigationContainer. Setting
<SafeAreaProvider style={{ backgroundColor: "black" }}>
did the trick.
I have solved the issue by disabling the sceneAnimationEnabled of the Tab Navigator.
<Tab.Navigator
sceneAnimationEnabled={false}>
{...}
</Tab.Navigator>
I solved this by setting lazy={false} in the <Tabs.Navigator> component:
<Tabs.Navigator
lazy={false}
>
cardStyle is an option on the screen, not the navigator.
<Stack.Navigator screenOptions={{ cardStyle: backgroundColor: material.containerBgColor }}>
{/* ... */}
</Stack.Navigator>
Or
<Stack.Navigator>
<Stack.Screen
name="Home"
component={AppTabNavigator}
options={{ cardStyle: backgroundColor: material.containerBgColor }}
/>
{/* ... */}
</Stack.Navigator>
Reference: https://reactnavigation.org/docs/en/next/stack-navigator.html#cardstyle
Probably a better way is to use the theming system to pass your colors rather than specifying it for every navigator: https://reactnavigation.org/docs/en/next/themes.html
The problem with me was that I had enableScreens() was enabled in my App.tsx.
You have 2 options:
Remove the enableScreens() call
add detachPreviousScreen: false to your screenOptions of your navigator and enableScreens(true) to your App.tsx
for expo you can change backgroundColor in App.json file to #000000.
The background color for your app, behind any of your React views. This is also known as the root view background color.
Put the outside your NavigationContainer with flex: 1 and backgroundColor with the color you like
I solved this problem doing this in the app.json file: (but i had the same background color on every page)
"expo": {
"backgroundColor": "#YOUR_COLOR",
}
I solved this problem with this code: you can also put cardStyleInterpolator in the options property of each <Screen>
const notAnimation = () => ({});
screenOptions={{ cardStyleInterpolator: notAnimation }}>
Using react-native-navigation:^4.4.4, the issue is resolved by disabling the animation.
const AppNavigator = createStackNavigator(
{...<YOUR_CONFIG>},
{
...
defaultNavigationOptions: {animationEnabled: false}, // Add this line
},
);
No need to worry about backgroundColor 👍
Try this , it will work -
Just wrap the navigator inside a view and give it a background color and don't forget to set flex
For me adding cardStyle was enough to fix it.
const navigatorOptions = {
...
cardStyle: { backgroundColor: 'transparent' },
...
}
Setting the background color merely "hides" the problem. For me, the problem arose when I switched to react-native-navigation:^6.0.0, but it only happened on screens where I was using LayoutAnimation.configureNext() in a useEffect callback (used to trigger effects when a state changes).
What completely solved the problem for me was to put the LayoutAnimation.configureNext() in the callback function that triggers the state change, instead of passively listening to it with useEffect (because it seemed that the useEffect trigger on render + the LayoutAnimation caused the flash).
I have solved this issue by wrapping navigationContainer inside the SafeAreaProvider which is imported from react-native-safe-area-context and give background color to it.
<SafeAreaProvider style={{backgroundColor: Colors?.backgroundColor}}>
<NavigationContainer>
<StackNavigator />
</NavigationContainer>
</SafeAreaProvider>
try it if this works fine, then give upvote and tick the answer.
Thanks