如何将TabBarTop与TabBarBottom作为自定义导航视图组件?react-navigation问题咨询
我懂你碰到的这个坑!当初我在自定义React Navigation导航器的时候也踩过类似的问题——TabBarTop在默认Tab导航器里正常工作,到了自定义导航器就抽风,核心原因就是我们没手动把navigationState传递给它,默认导航器帮我们做了这个隐式操作而已。
下面给你两种可行的解决思路,按需选择:
方案1:自定义导航器手动传递navigationState
如果你坚持要自己写自定义导航器,关键是要从上层导航状态中提取Tab对应的navigationState,然后手动传给TabBarTop:
import { View, Text } from 'react-native'; import { createStackNavigator } from '@react-navigation/stack'; import { TabBarTop } from '@react-navigation/material-top-tabs'; // 你的Tab页面组件 const TabScreen1 = () => <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Tab 1</Text></View>; const TabScreen2 = () => <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Tab 2</Text></View>; // 自定义导航器核心组件 const CustomTabNavigator = ({ navigation, route }) => { // 从上层导航状态中提取Tab的专属状态 const tabNavState = navigation.getState().routes.find(r => r.key === route.key).state; return ( <View style={{ flex: 1 }}> {/* Header和Tabs之间的自定义组件 */} <View style={{ padding: 16, backgroundColor: '#f5f5f5', borderBottomWidth: 1, borderColor: '#eee' }}> <Text style={{ fontSize: 16, textAlign: 'center' }}>我是中间自定义组件</Text> </View> {/* 关键:手动传递navigationState给TabBarTop */} <TabBarTop navigationState={tabNavState} onTabPress={({ route: tabRoute }) => { navigation.navigate(tabRoute.name); }} /> {/* 渲染当前选中的Tab页面 */} {tabNavState.routes[tabNavState.index].name === 'Tab1' ? <TabScreen1 /> : <TabScreen2 />} </View> ); }; // 用Stack导航器包裹自定义导航器 const Stack = createStackNavigator(); export const AppNavigator = () => ( <Stack.Navigator> <Stack.Screen name="CustomTab" component={CustomTabNavigator} options={{ headerTitle: '自定义导航示例' }} /> </Stack.Navigator> );
方案2:嵌套导航+Children渲染(更简单)
如果不需要完全自定义导航器逻辑,推荐用这种方式:在Stack导航器的页面中,直接嵌套Tab导航器,同时插入自定义组件。这种方式不需要手动处理状态传递,默认Tab导航器会帮我们搞定:
import { View, Text } from 'react-native'; import { createStackNavigator } from '@react-navigation/stack'; import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'; // 你的Tab页面组件 const TabScreen1 = () => <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Tab 1</Text></View>; const TabScreen2 = () => <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Tab 2</Text></View>; // 常规的Tab导航器 const TabNavigator = createMaterialTopTabNavigator(); const MyTabs = () => ( <TabNavigator.Navigator tabBar={props => <TabBarTop {...props} />}> <TabNavigator.Screen name="Tab1" component={TabScreen1} /> <TabNavigator.Screen name="Tab2" component={TabScreen2} /> </TabNavigator.Navigator> ); // Stack导航器包裹,插入自定义组件 const Stack = createStackNavigator(); export const AppNavigator = () => ( <Stack.Navigator> <Stack.Screen name="Home" options={{ headerTitle: '首页' }} // 用children而不是component,方便插入自定义组件 children={() => ( <View style={{ flex: 1 }}> {/* Header和Tabs之间的自定义组件 */} <View style={{ padding: 16, backgroundColor: '#f5f5f5', borderBottomWidth: 1, borderColor: '#eee' }}> <Text style={{ fontSize: 16, textAlign: 'center' }}>我是中间自定义组件</Text> </View> {/* 嵌套Tab导航器 */} <MyTabs /> </View> )} /> </Stack.Navigator> );
核心原因再啰嗦一句:TabBarTop本质上依赖react-native-tab-view的TabBar,而这个组件必须拿到navigationState才能正确渲染Tab项、高亮当前选中状态,默认Tab导航器内部已经帮我们把这个状态传递下去了,但自定义导航器里需要我们手动完成这一步。
内容的提问来源于stack exchange,提问作者user8815130
相关产品推荐
相关产品推荐

