[英]How to set always first screen of Stack Navigator inside Tab Navigator React Navigation 5
React Navigation 5反应导航 5
I've build a StackNavigator inside of a TabNavigator, and the navigation between home screen and other screens is working.我在 TabNavigator 内部构建了一个 StackNavigator,主屏幕和其他屏幕之间的导航正常。 But the problem is,When I move from Tab2 to Tab1 I expect Tab1 always show me first screen of StackNavigator.但问题是,当我从 Tab2 移动到 Tab1 时,我希望 Tab1 始终显示 StackNavigator 的第一个屏幕。
tab1
-> Stack
-screen1
-screen2
tab2
I am on screen2 and then move to tab2 after that then I move back to Tab1 I want to always display screen1.我在 screen2 上,然后移至 tab2,然后我移回 Tab1 我想始终显示 screen1。
I am try to use我正在尝试使用
OnTabPress({navigation})=>{
navigation.navigate("stackName",{
screen: "screen1"
}).
}
Its work but its show me screen2 first then navigate to screen1.它的工作,但它首先显示 screen2 然后导航到 screen1。 Is there any other Solution.有没有其他解决方案。 https://snack.expo.io/@usamasomy/groaning-donut https://snack.expo.io/@usamasomy/groaning-donut
Use unmountOnBlur: true in options.在选项中使用 unmountOnBlur: true 。 Eg.例如。
<Tab.Screen
name="Stack1"
component={Stack1}
options={{
tabBarLabel: "Stack1",
unmountOnBlur: true,
}}
/>
So when you are navigating away from this tab and you're on screen2 of Stack1, you will always come on the first screen of this stackNavigator when coming back to this tab.因此,当您离开此选项卡并位于 Stack1 的屏幕 2 时,当您返回此选项卡时,您将始终出现在此 stackNavigator 的第一个屏幕上。
initialRouteName= "NAME"
is the keyword to make sure you have a default and make sure you use navigate()
push()
pop()
accordingly. initialRouteName= "NAME"
是确保您拥有默认值并确保相应地使用navigate()
push()
pop()
的关键字。
Firstly, create a custom TabBar so we can write our own functions executed by onPress
首先,创建一个自定义的 TabBar,这样我们就可以编写自己的由onPress
执行的函数
function MyTabBar({ state, descriptors, navigation }) {
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const onPress = () => {
navigation.reset({
index: 0,
routes: [{ name: 'Screen1' }],
})
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
}}
const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};
Then in the TabScreens
override the original TabBar
in Tab.Navigator
by using tabBar=...
then call navigation.reset()
with index:0
and routes:{{name: 'Screen1'}}
every time MyTabBar
is pressed.然后在TabScreens
中,通过使用tabBar=...
覆盖MyTabBar
中的原始TabBar
,然后在每次Tab.Navigator
时使用index:0
和routes:{{name: 'Screen1'}}
调用navigation.reset()
。
const TabScreens = ()=>{
return(
<Tab.Navigator tabBar={props => <MyTabBar {...props} />} initialRouteName="Tab1Screens" >
<Tab.Screen
name = "Tab1Screens"
component = {Tab1Screens}
/>
<Tab.Screen
name = "Tab2Screens"
component = {Tab2Screens}
/>
</Tab.Navigator>
)
}
return (
<TouchableOpacity
accessibilityRole="button"
accessibilityStates={isFocused ? ['selected'] : []}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
onLongPress={onLongPress}
style={{ flex: 1 }}
>
<Text style={{ color: isFocused ? '#673ab7' : '#222' }}>
{label}
</Text>
</TouchableOpacity>
);
})}
</View>
);
}
This can be greatly improved eg:这可以大大改善,例如:
-some logic before `navigation.reset()`
-Accessing onPress without creating a new component
-etc..
finally snack available here: https://snack.expo.io/@karammarrie/customtabbar终于可以在这里买到零食了: https://snack.expo.io/@karammarrie/customtabbar
i have a simple solution is to set initialRouteName= "screen1" in我有一个简单的解决方案是设置 initialRouteName = "screen1"
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
initialRouteName="screen1"
>
<Stack.Screen name="screen1" component={Screen1} />
<Stack.Screen name="screen2" component={Screen2} />
</Stack.Navigator>
{/** **/}
if the screen still shows the first screen 2, you just need to comment the line <Stack.Screen name="screen2" component={Screen2} />
and reload the screen, then remove the comment line.如果屏幕仍然显示第一个屏幕 2,您只需注释行<Stack.Screen name="screen2" component={Screen2} />
并重新加载屏幕,然后删除注释行。
There is no documentation about it, but the following code worked for me:没有关于它的文档,但以下代码对我有用:
const navigationComp = useNavigation<StackNavigationProp<Screen1Stack>();
<Tab.Screen
name="Screen1 Tab"
component={Screen1StackScreen}
listeners={{
tabPress: () => {
navigationComp.replace('Screen 1 Child 1');
},
}}
/>
The code above always navigates to the 'Screen 1 Child 1' when the "Screen1 Tab" is pressed.当按下“Screen1 Tab”时,上面的代码总是导航到“Screen 1 Child 1”。
like this像这样
e电子
xport default function BottonTab() {
const tabOffsetValue = useRef(new Animated.Value(0)).current;
return (
<View style={{flex: 1, backgroundColor: colors.primaryColor}}>
<Tab.Navigator
initialRouteName="Home"
screenOptions={{
showLabel: false,
tabBarShowLabel: false,
headerShown: false,
tabBarStyle: {
backgroundColor: colors.white,
position: 'absolute',
bottom: hp(0.51),
marginHorizontal: wp(2),
height: hp(8),
borderRadius: wp(2),
shadowColor: '#000',
shadowOpacity: 0.06,
shadowOffset: {
width: 10,
height: 10,
},
paddingHorizontal: 20,
},
}}>
<Tab.Screen
name={'Home'}
component={HomeScreen}
options={{
title: 'Home',
showLabel: false,
tabBarIcon: ({focused}) => (
<View>
<FontAwesome5
name="home"
size={wp(6)}
color={
focused ? colors.primaryColor : colors.secondaryTextColor
}
/>
</View>
),
}}
listeners={({navigation, route}) => ({
tabPress: e => {
Animated.spring(tabOffsetValue, {
toValue: getWidth() * 0,
useNativeDriver: true,
}).start();
},
})}
/>
<Tab.Screen
name={'HelpDiskScreen'}
component={HelpDiskScreen}
options={{
title: 'HelpDisk',
tabBarIcon: ({focused}) => (
<View>
<FontAwesome5
name="search"
size={wp(6)}
color={
focused ? colors.primaryColor : colors.secondaryTextColor
}
/>
</View>
),
}}
listeners={({navigation, route}) => ({
tabPress: e => {
Animated.spring(tabOffsetValue, {
toValue: getWidth() * 1.22,
useNativeDriver: true,
}).start();
},
})}
/>
<Tab.Screen
name={'ManageBookingScreen'}
component={ManageBookingScreen}
options={{
title: 'Manage',
tabBarIcon: ({focused}) => (
<View>
<Feather
name="settings"
size={wp(6)}
color={
focused ? colors.primaryColor : colors.secondaryTextColor
}
/>
</View>
),
}}
listeners={({navigation, route}) => ({
tabPress: e => {
Animated.spring(tabOffsetValue, {
toValue: getWidth() * 2.52,
useNativeDriver: true,
}).start();
},
})}
/>
<Tab.Screen
name={'ParkyingTypesScreen'}
component={ParkyingTypesScreen}
options={{
title: 'Parking',
tabBarIcon: ({focused}) => (
<View>
<FontAwesome5
name="bell"
size={wp(6)}
color={
focused ? colors.primaryColor : colors.secondaryTextColor
}
/>
</View>
),
}}
listeners={({navigation, route}) => ({
tabPress: e => {
Animated.spring(tabOffsetValue, {
toValue: getWidth() * 3.82,
useNativeDriver: true,
}).start();
},
})}
/>
</Tab.Navigator>
<Animated.View
style={{
width: getWidth(),
marginLeft: getWidth() * 0.58,
height: 2,
backgroundColor: colors.primaryColor,
bottom: hp(7),
borderRadius: 20,
transform: [{translateX: tabOffsetValue}],
}}></Animated.View>
</View>
);
}
Another option is to clear the stack of the navigation before navigating, so when you return to that screen, the navigation starts from the top另一种选择是在导航之前清除导航的堆栈,因此当您返回到该屏幕时,导航从顶部开始
navigation.dispatch(StackActions.popToTop());
navigation.navigate("NextScreen");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.