ReactNative系列(六):react-natigatio
ReactNative整理:《ReactNative系列》
内容目录
一、前言
二、思路与架构
三、导航搭建
四、结束
一、前言
前面两篇分别介绍了react-navigation
的基本导航类型属性和单个导航的使用方式及需要注意的典型配置属性。这篇介绍一下导航类型的嵌套使用。
项目中的导航器基本都是多种导航的相互嵌套来实现的,常见的有StactNavigator
和TabNavigator
嵌套,或者StackNavigator
和DrawerNavigator
嵌套。这里我们以Demo为例,聊一下导航器的嵌套使用。
二、思路与架构
应用中的导航架构是根据不同需求来搭建的,具体情况需要具体对待,我们可以对导航器架构进行假设。
一个应用中往往在启动时会有广告页,几秒之后再进入主页,广告页不会二次出现 -- 可以用SwitchNavigator
;主页常见的样式是以底部标签的形式来展示 -- TabNavigator
,页面间的跳转则需要堆栈导航来实现 -- StackNavigator
,侧滑菜单可以酌情使用 -- DrawerNavigator
。
嵌套方式:SwitchNavigator
为最外层导航,其包含的两个单页面分别为广告页,以及真正处理业务的页面组成的StackNavigator
,用TabNavigator
作为堆栈导航的默认第一个页面。
三、导航搭建
根据思路开始搭建导航框架:
1、最外层的导航是用SwitchNavigator
,其中包含两个页面,一个是广告页面,另外一个是由多个页面构成的StackNavigator
。
/**
* SplashView - 应用广告页面
* MainContainer - 多个页面组合成的堆栈导航
*/
const SwitchConstruct = createSwitchNavigator({
splash: {
screen: SplashView
},
main: {
screen: MainContainer
}
}, {
initialRouteName: 'splash',
backBehavior: 'none'
});
export default ApplicationContainer = createAppContainer(SwitchConstruct);
其中MainContainer
就是由以标签导航为默认首页展示的StackNavigator
,新创建的页面都可以加到该堆栈导航中。
需要注意:只有最外层的SwitchNavigator
需要通过createAppContainer
链接到应用,其余导航因为是以组件的形式嵌套使用,所以不需要。
2、堆栈导航中的默认第一个页面为TabNavigator
。将主页要展示的三个标签页组合成标签导航加到StackNavigator
中。
export default MainContainer = createStackNavigator({
tab: {
screen: TabContainer
},
}, {
headerMode: 'none',
});
MainContainer
中的所有页面都是去掉了系统默认的header
--headerMode: 'none'
,建议使用自己封装的顶部Header,更灵活也更方便移植。
export default TabContainer = createBottomTabNavigator({
Home: {
screen: HomeClass,
navigationOptions: {
title: '首页',
tabBarLabel: '首页',
tabBarIcon: ({ focused, horizontal, tintColor }) => (
<Image
source={focused ? tab_home_select : tab_home}
style={{ width: 20, height: 20 }}
resizeMode={'contain'}
/>
)
}
},
List: {
screen: ListClass,
navigationOptions: {
title: '书单',
tabBarLabel: '书单',
tabBarIcon: ({ focused, horizontal, tintColor }) => (
<Image
source={focused ? tab_list_select : tab_list}
style={{ width: 20, height: 20 }}
resizeMode={'contain'}
/>
)
}
},
Slide: {
screen: SlideContainer,
navigationOptions: {
title: '我的',
tabBarLabel: '我的',
tabBarIcon: ({ focused, horizontal, tintColor }) => (
<Image
source={focused ? tab_self_select : tab_self}
style={{ width: 20, height: 20 }}
resizeMode={'contain'}
/>
)
}
}
}, {
lazy: true,
initialRouteName: 'Home',
order: ['Home', 'List', 'Slide'],
tabBarOptions: {
activeTintColor: '#FF8800',
inactiveTintColor: '#666666',
showIcon: true,
labelStyle: {
fontSize: 12
},
style: {
backgroundColor: 'white',
height: 45
}
}
});
3、TabContainer
中有一个为侧滑导航,SlideContainer
中同样可以包含多个页面。SelfClass
、InfoClass
和SettingClass
三个页面被DrawerNavigator
包裹,侧滑页面的item没有用react-navigation
中的DrawerItems
,而是自定义的,使用起来更好控制,效果更多变,个人更推荐自定义封装。
export default SlideContainer = createDrawerNavigator({
Self: {
screen: SelfClass
},
Information: {
screen: InfoClass
},
Setting: {
screen: SettingClass
}
}, {
drawerWidth: 300,
drawerPosition: 'right',
order: ['Self', 'Information', 'Setting'],
initialRouteName: 'Self',
drawerLockMode: 'locked-closed',
drawerType: 'slide',
contentComponent: (props) => {
return (
<ScrollView style={{flex: 1, margin: 30}}>
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItemList {...props} />
</SafeAreaView>
</ScrollView>
);
},
contentOptions: {
activeTintColor: '#FF8800',
inactiveTintColor: '#666666',
}
});
class DrawerItemList extends Component {
constructor(props) {
super(props);
}
itemPress(itemName) {
Alert.alert('提示', itemName, [{text: '确定', onPress: () => {}}])
}
render() {
return this.props.items.map((item, index) => {
let itemName = '';
if (item.key === 'Self') {
itemName = '我的';
} else if (item.key === 'Information') {
itemName = '个人信息';
} else {
itemName = '系统设置';
}
return (
<TouchableOpacity
key={index}
style={styles.itemContainer}
onPress={() => this.itemPress(itemName)}
>
<Text style={styles.itemText}>{itemName}</Text>
</TouchableOpacity>
);
});
}
}
每个页面的顶部标题栏可以自行封装,通过父组件向子组件传递props
的方式来传递所需要的数据。标题左右两侧的按钮也可以通过属性值控制 -- 展示文本或图片。
/**
* 标题顶部的左右两侧按键可以通过传递类型来区分
* leftType:左侧按钮类型 -- 图片或文字
* rightType:右侧按钮类型 -- 图片或文字
*/
export default class BaseTitle extends Component {
constructor(props) {
super(props);
}
renderLeftView(leftType) {
if (leftType === 1) {
return (
<Image
style={styles.leftImage}
source={BackImage}
/>
);
}
return null;
}
renderRightView(rightType) {
if (rightType === 1) {
return (
<Image
style={styles.rightImage}
source={this.props.rightImage}
/>
);
}
return null;
}
render() {
const { leftType, rightType, title } = this.props;
return (
<View style={styles.constainer}>
<TouchableOpacity
style={styles.leftView}
onPress={() => {
if (leftType !== 0) {
this.props.onLeftPress();
}
}}
>
{this.renderLeftView(leftType)}
</TouchableOpacity>
<View style={styles.titleView}>
<Text
style={styles.titleText}
numberOfLines={1}
>
{title}
</Text>
</View>
<TouchableOpacity
style={styles.rightView}
onPress={() => {
if (rightType !== 0) {
this.props.onRightPress();
}
}}
>
{this.renderRightView(rightType)}
</TouchableOpacity>
</View>
);
}
}
4、演示效果
四、结束
SwitchNavigator
为最上层导航,包含StackNavigator
--> StackNavigator
用作主体逻辑页面控制导航,包含TabNavigator
--> TabNavigator
用作可切换标签的首页导航,包含DrawerNavigator
--> DrawerNavigator
用作侧滑菜单展示,包含侧滑菜单页面。
这里更主要的是强调导航的嵌套方式,各类导航的具体属性没有过多展示,实际应用中需要根据需求做出调整。 各个导航器中的路由页面比较简单,没有具体的代码展示。到这里整个react-navigation
就介绍完了,希望能帮到大家。
发现有问题的地方希望大家指出,共同讨论,喜欢的可以点赞关注