9

【React Native教程】Stack Navigation与Tab Navigation嵌套最佳实践

 3 years ago
source link: https://anye3210.github.io/2020/12/07/【React-Native教程】StackNavigation与TabNavigation嵌套最佳实践/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

上一篇文章详细讲解了 react-navigation 的使用,这篇文章主要说一下 Stack NavigationTab Navigation 嵌套的问题。

在iOS原生开发中,一般是在 TabController 里嵌套 NavigationController ,也就是说底部导航控制器里放多个堆栈导航控制器,每个堆栈导航控制器控制有独立的堆栈和状态。

但如果在使用 react-navigation 进行这种嵌套方式,由于根控制器是底部的 TabNavigation ,每次跳转到子控制器时,底部的导航栏不会隐藏。官方文档说可以用属性更改的方法隐藏底部导航栏,但不推荐,会影响性能。因此本文主要讲解如何使用堆栈导航器中嵌套底部导航控制器来解决这个问题。

实现方式

首先将 Main 控制器放入 Stack Navigation 中:

class App extends Component {

	render() {
	    return (
	        <NavigationContainer>
	            <Stack.Navigator>
	                <Stack.Screen
	                    key="Main"
	                    name="Main"
	                    component={Main}
	                    options={({route}) => ({
	                        headerTitle: route.name
	                    })}
	                />
	            </Stack.Navigator>
	        </NavigationContainer>
	    );
	}
	
}

然后实现 Main 控制器

const Main = ({navigation, route}) => {

    return (
        <Tab.Navigator
            screenOptions={({ route }) => ({
                tabBarIcon: ({ focused, color, size }) => {``
                    return (
                        <Image style = {{ width: 25, height: 25 }}
                               source = {this.iconImage(route, focused)}
                        />);
                },
            })}
            tabBarOptions={{
                activeTintColor: '#32B7FF',
                inactiveTintColor: 'gray',
            }}
        >
            <Tab.Screen name="Home" component={HomeScreen} options={{title: 'Home'}}/>
            <Tab.Screen name="Settings" component={SettingsScreen} options={{title: 'Settings'}}/>
        </Tab.Navigator>
    );
}

function iconImage(route, focused) {
    let image;
    if (route.name === 'Home') {
        image = focused
            ? require('../../images/homePage_sel.png')
            : require('../../images/homePage_nor.png');
    } else {
        image = focused
            ? require('../../images/setting_sel.png')
            : require('../../images/setting_nor.png');
    }
    return image;
}

上面 HomeSetting 页面的实现这里就不再赘述,实现之后运行会发一 HomeSetting 顶部导航栏的标题和样式都是相同的,也就是 Main 控制器的。这是由于 Tab Navigation 作为 Stack Navigation 的根控制器,顶部导航栏的标题都是按照根控制器的设置来显示的。要实现 Tab Navigaiton 的子控制器都有自己的独立顶部导航栏,需要使用 ReactHook 方法,在 return 前面加上:

React.useLayoutEffect(() => {
    navigation.setOptions({
      headerTitle: this.getHeaderTitle(route),
      headerRight: this.getHeaderRight(route),
      headerLeft: this.getHeaderLeft(route),
    });
  }, [navigation, route]);
  
getHeaderTitle(route) {
  const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';
  switch (routeName) {
    case 'Home':
      return '首页';
	case 'Settings':
      return '系统设置';
  }
}

这里使用了 ReactuseLayoutEffect 方法,这个方法会从 DOM 里读取布局并同步把新布局添加了布局更新计划中,等一下次重新绘制就会更新上去。在方法中通过 route 名称动态地改变了导航栏的标题和左右侧的按钮,当底部导航栏按钮被点击进行切换时,顶底的导航栏显示也会同步更新。

至此, Stack NavigationTab Navigation 嵌套时保证跳转时隐藏底部导航栏的最佳实践就完成了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK