本文内容
1、navigation、tabbar 的分离、navigation的使用
2、传值、回调
3、每个页面设置 navigator
4、navigation reset方法
5、关于返回指定页面(原)
5、关于返回指定页面(新)
程序目录
一、navigation、tabbar 的分离、navigation的使用
index.ios.js
require('./AppRoot/root');
root.js
/**
* Created by mymac on 2017/8/18.
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
import {StackNavigator} from "react-navigation";
import Navigator from './natigation';
/*
navigation 构造函数
*/
const Navigation = StackNavigator(Navigator.AppNavigationRouterConfigs, Navigator.AppNavigationStackConfigs);
class MainComponent extends Component {
render() {
return (
<Navigation
onNavigationStateChange={(prevNav, nav, action)=>{
// 每次导航改变时,都会走这个方法,可以再次判断逻辑
console.log('prevNav=',prevNav);
console.log('nav=',nav);
console.log('action=',action);
/>
);
}
}
AppRegistry.registerComponent('Navigation', () => MainComponent);
navigation.js
/**
* Created by mymac on 2017/8/18.
*/
import {TabNavigator} from "react-navigation";
import FirstCtrl from '../controllers/firstCtrl';
import SecondCtrl from '../controllers/secondCtrl';
import ThirdCtrl from '../controllers/thirdCtrl';
import AppTab from './tabBar';
// 动画效果
// forHorizontal:从右向左进入
// forVertical:从下向上进入
// forFadeFromBottomAndroid:从底部淡出
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';
/*
title - 可以作为头部标题 headerTitle ,或者Tab标题 tabBarLabel
header - 自定义的头部组件,使用该属性后系统的头部组件会消失
headerTitle - 头部的标题,即页面的标题
headerBackTitle - 返回标题,默认为 title
headerTruncatedBackTitle - 返回标题不能显示时(比如返回标题太长了)显示此标题,默认为 “Back”
headerRight - 头部右边组件
headerLeft - 头部左边组件
headerStyle - 头部组件的样式
headerTitleStyle - 头部标题的样式
headerBackTitleStyle - 头部返回标题的样式
headerTintColor - 头部颜色
headerPressColorAndroid - Android 5.0 以上MD风格的波纹颜色
gesturesEnabled - 否能侧滑返回, iOS 默认 true , Android 默认 false
*/
/*
构造函数
*/
const Tab = TabNavigator(AppTab.AppRootTabBarRouteConfigs, AppTab.AppRootTabBarNavigatorConfigs);
/* 配置路由,所有要跳转的页面都需要在此声明 */
const AppNavigationRouterConfigs = {
TabBar: {
screen: Tab,
navigationOptions: ({navigation}) => ({
title: '首页',
headerBackTitle: '首页', // 给下一个页面的返回按钮设置标题 , 类似iOS的 backBarItem
}),
},
First: {
screen: FirstCtrl,
navigationOptions: ({navigation}) => ({
title: '第一页',
headerBackTitle: '第一页', // 给下一个页面的返回按钮设置标题
}),
},
Second: {
screen: SecondCtrl,
navigationOptions: ({navigation}) => ({
title: '第二页',
headerBackTitle: '第二页', // 给下一个页面的返回按钮设置标题
}),
},
Third: {
screen: ThirdCtrl,
navigationOptions: ({navigation}) => ({
title: '第三页',
headerBackTitle: '第三页', // 给下一个页面的返回按钮设置标题
}),
}
};
/*
initialRouteName - 导航器组件中初始显示页面的路由名称,如果不设置,则默认第一个路由页面为初始显示页面
initialRouteParams - 给初始路由的参数,在初始显示的页面中可以通过 this.props.navigation.state.params 来获取
navigationOptions - 路由页面的配置选项,它会被 RouteConfigs 参数中的 navigationOptions 的对应属性覆盖。
paths - 路由中设置的路径的覆盖映射配置
mode - 页面跳转方式,有 card 和 modal 两种,默认为 card :
card - 原生系统默认的的跳转
modal - 只针对iOS平台,模态跳转
headerMode - 页面跳转时,头部的动画模式,有 float 、 screen 、 none 三种:
float - 渐变,类似iOS的原生效果
screen - 标题与屏幕一起淡入淡出
none - 没有动画
cardStyle - 为各个页面设置统一的样式,比如背景色,字体大小等
transitionConfig - 配置页面跳转的动画,覆盖默认的动画效果
onTransitionStart - 页面跳转动画即将开始时调用
onTransitionEnd - 页面跳转动画一旦完成会马上调用
*/
const AppNavigationStackConfigs = {
initialRouteName: 'TabBar',
initialRouteParams: {initParams: '初始化时传递参数'},
navigationOptions: {
title: '路由页面的配置选项,它会被 RouteConfigs 参数中的 navigationOptions 的对应属性覆盖',
},
mode: 'card',
headerMode: 'screen',
transitionConfig: ()=>({
screenInterpolator: CardStackStyleInterpolator.forHorizontal,
}),
onTransitionStart: (() => {
console.log('页面跳转动画开始');
}),
onTransitionEnd: (() => {
console.log('页面跳转动画结束');
}),
};
export default {
AppNavigationRouterConfigs,
AppNavigationStackConfigs
};
tabBar.js
/**
* Created by mymac on 2017/8/18.
*/
import React, { Component } from 'react';
import {TabBarBottom} from "react-navigation";
import Home from '../subTabBars/select';
import Follow from '../subTabBars/follow';
import Explor from '../subTabBars/explor';
import Mine from '../subTabBars/mine';
/*自定义的 tabBar 图片 view*/
import TabBarItem from './tabBarItem';
/*
创建下面的四个 tabar
*/
const AppRootTabBarRouteConfigs = {
Home:{
screen: Home,
navigationOptions: {
tabBarLabel: '首页',
tabBarIcon: ({focused, tintColor}) => (
<TabBarItem
focused={focused}
normalImage={require('../images/select.png')}
selectedImage={require('../images/select_select.png')}
/>
),
}
},
Follow:{
screen: Follow,
navigationOptions: {
tabBarLabel: '关注',
tabBarIcon: ({focused, tintColor}) => (
<TabBarItem
focused={focused}
normalImage={require('../images/follow_follow.png')}
selectedImage={require('../images/follow_follow_select.png')}
/>
),
tabBarOnPress:(obj)=>{
console.log(obj);
obj.jumpToIndex(obj.scene.index)
},
}
},
Explor:{
screen: Explor,
navigationOptions: {
tabBarLabel: '发现',
tabBarIcon: ({focused, tintColor}) => (
<TabBarItem
focused={focused}
normalImage={require('../images/explor_explor.png')}
selectedImage={require('../images/explor_explor_select.png')}
/>
),
}
},
Mine:{
screen: Mine,
navigationOptions: {
tabBarLabel: '我的',
tabBarIcon: ({focused, tintColor}) => (
<TabBarItem
focused={focused}
normalImage={require('../images/mine_mine.png')}
selectedImage={require('../images/mine_mine_select.png')}
/>
),
}
},
};
/*
tabBarComponent - Tab选项卡组件,有 TabBarBottom 和 TabBarTop 两个值,在iOS中默认为 TabBarBottom ,在Android中默认为 TabBarTop 。
TabBarTop - 在页面的顶部
TabBarBottom - 在页面的底部
tabBarPosition - Tab选项卡的位置,有 top 或 bottom 两个值
swipeEnabled - 是否可以滑动切换Tab选项卡
animationEnabled - 点击Tab选项卡切换界面是否需要动画
lazy - 是否懒加载页面
initialRouteName - 初始显示的Tab对应的页面路由名称
order - 用路由名称数组来表示Tab选项卡的顺序,默认为路由配置顺序
paths - 路径配置
backBehavior - androd点击返回键时的处理,有 initialRoute 和 none 两个值
initailRoute - 返回初始界面
none - 退出
tabBarOptions - Tab配置属性,用在 TabBarTop 和 TabBarBottom 时有些属性不一致:
用于 TabBarTop 时:
activeTintColor - 选中的文字颜色
inactiveTintColor - 未选中的文字颜色
showIcon - 是否显示图标,默认显示
showLabel - 是否显示标签,默认显示
upperCaseLabel - 是否使用大写字母,默认使用
pressColor - android 5.0以上的MD风格波纹颜色
pressOpacity - android 5.0以下或者iOS按下的透明度
scrollEnabled - 是否可以滚动
tabStyle - 单个Tab的样式
indicatorStyle - 指示器的样式
labelStyle - 标签的样式
iconStyle - icon的样式
style - 整个TabBar的样式
用于 TabBarBottom 时:
activeTintColor - 选中Tab的文字颜色
activeBackgroundColor - 选中Tab的背景颜色
inactiveTintColor - 未选中Tab的的文字颜色
inactiveBackgroundColor - 未选中Tab的背景颜色
showLabel - 是否显示标题,默认显示
style - 整个TabBar的样式
labelStyle - 标签的样式
tabStyle - 单个Tab的样式
*/
/*
TabBarTop:
indicatorStyle: {height: 0}, // android 中TabBar下面会显示一条线,高度设为 0 后就不显示线了, 不知道还有没有其它方法隐藏???
showIcon: true, // android 默认不显示 icon, 需要设置为 true 才会显示
*/
const AppRootTabBarNavigatorConfigs = {
initialRouteName: 'Home',
defaultNavigationOptions: {
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
},
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
lazy: true,
tabBarOptions: {
activeTintColor: 'red',
inactiveTintColor: 'black',
showLabel: true,
style:{ // 在此处可以设置tabbar的属性,height、marginBottom等。iPhone X适配时,需要在此处进行适配处理
backgroundColor: 'yellow',
},
labelStyle: { // 在此处可以设置tabbar的title的属性,大小、颜色等
fontWeight: 'bold',
fontSize: 12,
},
iconStyle: {
// 在此处可以设置tabbar的icon的属性
}
}
};
export default {
AppRootTabBarRouteConfigs,
AppRootTabBarNavigatorConfigs
};
/* 在此直接导出 Tab ,在 navigation 里面是得不到的,只有在 navigation 里面 调用构造方法*/
/*
构造函数
export default Tab = TabNavigator(AppTab.AppRootTabBarRouteConfigs, AppTab.AppRootTabBarNavigatorConfigs);
*/
二、传值、回调
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
} from 'react-native';
export default class select extends Component {
render() {
const {navigate,} = this.props.navigation;
return (
<View style={styles.container}>
<Text style={styles.welcome}>
精选
</Text>
<TouchableOpacity style={{marginTop: 20}} onPress={()=>{
// 传递参数,及 回调函数
navigate('First', {params: '你好第一页', callBack:(value)=>{
console.log(value);
}});
}}>
<Text style={styles.welcome}>
点击跳转到第一个页面
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
/**
* Created by mymac on 2017/8/18.
*/
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity
} from 'react-native';
export default class firstCtrl extends Component {
render() {
const {navigate} = this.props.navigation;
// 收到的参数
const {params} = this.props.navigation.state;
return (
<View style={styles.container}>
<Text style={styles.welcome}>
上一个页面给当前页传值为:{params.params}
</Text>
<TouchableOpacity style={{marginTop: 20}} onPress={()=>{
navigate('Second', {params: '你好第二页'});
}}>
<Text style={styles.welcome}>
点击跳转到第二个页面
</Text>
</TouchableOpacity>
<TouchableOpacity style={{marginTop: 100}} onPress={()=>{
//回调函数
params.callBack('123456789');
this.props.navigation.goBack();
}}>
<Text style={styles.welcome}>
点击返回首页,并传值:"hello world"
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});
三、每个页面设置 navigator
* Created by mymac on 2017/8/18.
*/
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity
} from 'react-native';
export default class firstCtrl extends Component {
/*
title - 可以作为头部标题 headerTitle ,或者Tab标题 tabBarLabel
header - 自定义的头部组件,使用该属性后系统的头部组件会消失
headerTitle - 头部的标题,即页面的标题
headerBackTitle - 返回标题,默认为 title
headerTruncatedBackTitle - 返回标题不能显示时(比如返回标题太长了)显示此标题,默认为 “Back”
headerRight - 头部右边组件
headerLeft - 头部左边组件
headerStyle - 头部组件的样式
headerTitleStyle - 头部标题的样式
headerBackTitleStyle - 头部返回标题的样式
headerTintColor - 头部标题颜色
headerPressColorAndroid - Android 5.0 以上MD风格的波纹颜色
gesturesEnabled - 否能侧滑返回, iOS 默认 true , Android 默认 false
*/
/*
static navigationOptions = ({ navigation, navigationOptions, screenProps }) => {
return {
title: navigation.getParam('otherParam', 'A Nested Details Screen'),
headerRight: (
<Text>right</Text>
),
headerTitle: <customTitle/> 自定义标题组件。
};
};
*/
static navigationOptions = {
title:'第一个页面自定义标题', // 或者 headerTitle:'第一个页面自定义标题'
headerRight: (
<Text>right</Text>
),
//headerLeft: null, 没有返回按钮
headerTintColor: 'red',
header:null, // 隐藏 导航条
};
render() {
return (
<View style={styles.container}>
</View>
);
}
}
四、navigation reset方法
import { NavigationActions } from 'react-navigation'
重新注册导航栈,将原来的清空
const resetAction = NavigationActions.reset({
index: 0, // 默认选中第一个元素
actions: [
NavigationActions.navigate({ routeName: 'Profile'}) // Profile将这个js放入导航栈中
]
})
this.props.navigation.dispatch(resetAction)
import { NavigationActions } from 'react-navigation'
const resetAction = NavigationActions.reset({
index: 1, // 默认选中第二个 元素, 如果此处写为 2 这越界了,因为下面栈里只有两个元素
actions: [
NavigationActions.navigate({ routeName: 'Profile'}), // Profile将这个js放入导航栈中,第一个元素
NavigationActions.navigate({ routeName: 'Settings'}) // Settings将这个js放入导航栈中,第二个元素
]
})
this.props.navigation.dispatch(resetAction)
5、关于返回指定页面(原)
原思路:每一个页面进行navigate的时候都有一个key,所以在使用goBack(key)的时候,只要知道要返回页面的key就可以了。方法就是把页面的key存起来,存在redux中
<Navigation onNavigationStateChange={(prevNav, nav, action)=>{
// 每次导航改变时,都会走这个方法,可以再次判断逻辑,比如切换tabar需要调用方法
console.log('prevNav=',prevNav);
console.log('nav=',nav);
console.log('action=',action);
let route = {};
nav.routes.map((item)=>{
route[item.routeName] = item.key
});
console.log('route:',route);
this.props.saveRouteNameAndId(route);
}}/>
5、关于返回指定页面(新),请更新react-navigation到最新
再也不用去存key啦~
this.props.navigation 提供的几种方法:
goBack
navigate
pop
popToTop
getParam
push
replace
this.props.navigation.pop(2) // 2就是要返回几个页面
this.props.navigation.popToTop() // 直接返回到主导航
this.props.navigation.push('HomeDetail1')
// push 和 navigate效果一样