本文是基于最新的react-navigation^2.9.1来书写的。
要感谢挂着铃铛的兔
看到一篇不错的介绍,这里做下记录
react-native-router-flux使用技巧(API篇)
识兔,一款用来识别图片的开源项目,在未来还会添加更多有意思的东西
react-navigation的Demo
react-navigation使用技巧(进阶篇)
什么是react-navigation?
react-native
从开源至今,一直存在几个无法解决的毛病,偶尔就会复发让人隐隐作痛,提醒你用的不是原生,其中包括列表的复用问题,导航跳转不流畅的问题等等。
终于facebook坐不住了,在前一段时间开始推荐使用react-navigation
,并且在0.44发布的时将之前一直存在的Navigator
废弃了。
react-navigation
是致力于解决导航卡顿,数据传递,Tabbar和navigator布局,支持redux
。虽然现在功能还不完善,但基本是可以在项目中推荐使用的。
属性
react-navigation
分为三个部分。
StackNavigator
类似顶部导航条,用来跳转页面和传递参数。
TabNavigator
类似底部标签栏,用来区分模块。
DrawerNavigator
抽屉,类似从App左侧滑出一个页面,在这里不做讲解。
下面会分开讲解官网提供的配置方法,但顺序可能会官网不一样。
React-Navigation V2版使用教程
距离我上一个版本的react-navigation
教程已经有1年多的时间了,虽然一直在缝缝补补,但那个教程真的老了。正好react-navigation V2版本
也即将要正式发布了,趁着这次机会重新梳理一下教程,并把之前的坑和遗憾填补一下。
我会将本文分成三部分,第一部分是使用小技巧,第二部分是介绍API,第三部分是常用属性方法。
跳转
navigate('Detail',{
title:'图片详情',
url:item.url,
});
Detail
:在StackNavigator中注册的页面,需要一一对应,才能跳转到相应的页面
title
:在跳转的页面可以通过this.props.navigation.state.params.title
获取到这个参数。当然这个参数可以随便填写,都可以通过this.props.navigation.state.params.xxx
获取。
回调传参
navigate('Detail',{
// 跳转的时候携带一个参数去下个页面
callback: (data)=>{
console.log(data); // 打印值为:'回调参数'
}
});
const {navigate,goBack,state} = this.props.navigation;
// 在第二个页面,在goBack之前,将上个页面的方法取到,并回传参数,这样回传的参数会重走render方法
state.params.callback('回调参数');
goBack();
自定义
项目中基本是没可能用自带的那个导航条的,自带导航条左侧的按钮永远是蓝色的,如果我们需要更改按钮颜色,就需要用到自定义的功能了。
const StackOptions = ({navigation}) => {
console.log(navigation);
let {state,goBack} = navigation;
// 用来判断是否隐藏或显示header
const visible= state.params.isVisible;
let header;
if (visible === true){
header = null;
}
const headerStyle = {backgroundColor:'#4ECBFC'};
const headerTitle = state.params.title;
const headerTitleStyle = {fontSize:FONT_SIZE(20),color:'white',fontWeight:'500'}
const headerBackTitle = false;
const headerLeft = (
}
onPress={()=>{goBack()}}
/>
);
return {headerStyle,headerTitle,headerTitleStyle,headerBackTitle,headerLeft,header}
};
然后通过下面的方法调用就可以自定制导航了。
const MyApp = StackNavigator({
MyTab: {
screen: MyTab,
},
Detail: {
screen: Detail,
navigationOptions: ({navigation}) => StackOptions({navigation})
},
)};
在页面中使用的时候,在跳转页面的时候需要传递title
参数,才能看到效果哦。
自定义tabbar
早上有人问我,tabbar的图标可不可以使用原图,选中状态下可不可以设置其他图标。研究了一下官方文档,发现tabBarIcon
除了tintColor
还有另一个属性,用来判断选中状态的focused
。
tabBarIcon: ({tintColor,focused}) => (
focused
?
:
),
通过判断focused
,选中状态下使用识兔
图标,未选中状态使用干货
图标。
如果想使用图标原来的样子,那就将style
的tintColor
去掉,这样就会显示图标原本的颜色。
再封装
export const TabOptions = (tabBarTitle,normalImage,selectedImage,navTitle) => {
// console.log(navigation);
const tabBarLabel = tabBarTitle;
console.log(navTitle);
const tabBarIcon = (({tintColor,focused})=> {
return(
focused
?
:
)
});
const headerTitle = navTitle;
const headerTitleStyle = {fontSize:FONT_SIZE(20),color:'white'};
// header的style
const headerStyle = {backgroundColor:'#4ECBFC'};
return {tabBarLabel,tabBarIcon,headerTitle,headerTitleStyle,headerStyle};
};
在static中使用this方法
我之前文章中是将navaigationOptions
的方法写在了app.js
中,没有在页面中通过static navaigationOptions
来初始化页面,这段时间刚好有人问,所以在这里就写一下该怎么弄。
首先需要在componentDidMount(){}中动态的添加点击事件
属性给params
componentDidMount(){
this.props.navigation.setParams({
title:'自定义Header',
navigatePress:this.navigatePress
})
}
navigatePress = () => {
alert('点击headerRight');
console.log(this.props.navigation);
}
接下来就可以通过params方法来获取点击事件了
static navigationOptions = ({ navigation, screenProps }) => ({
title: navigation.state.params?navigation.state.params.title:null,
headerRight:(
返回
)
});
让安卓实现push动画
之前我群里的讨论怎么让安卓实现类似iOS的push动画,后来翻看官方issues的时候,真的发现了实现push动画的代码,在这里共享下
// 先引入这个方法
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';
// 在StackNavigator配置headerMode的地方,使用transitionConfig添加
{
headerMode: 'screen',
transitionConfig:()=>({
screenInterpolator:CardStackStyleInterpolator.forHorizontal,
})
}
关于goBack返回指定页面
react-navigation
是提供了goBack()到指定页面的方法的,那就是在goBack()中添加一个参数,但当你使用goBack('Main')
的时候,你会发现并没有跳转,原因是react-navigation默认goBack()中的参数是系统随机分配的key
,而不是手动设置的routeName
,而方法内部又没有提供可以获得key
的方法,所以这里只能通过修改源码将key
换成routeName
了。
下面的内容直接引用了hello老文
的内容
把项目/node_modules/react-navigation/src/routers/StackRouter.js文件里的
const backRoute = state.routes.find((route: *) => route.key === action.key);
改成 const backRoute = state.routes.find(route => route.routeName === action.key);
但不是很完美, 这里的component要填想返回的组件的前一个组件的routeName, 比如你的栈里顺序是home1, home2, home3, home4, 在home4里要返回home2, 使用this.props.navigation.goBack('home3');; 并且又会带出一个问题: goBack()方法没反应了, 必须加个null进去, 写成goBack(null)...
关于goBack返回指定页面的修改完善版
if (action.type === NavigationActions.BACK) {
let backRouteIndex = null;
if (action.key) {
const backRoute = state.routes.find(
/* $FlowFixMe */
/* 修改源码 */
route => route.routeName === action.key
/* (route: *) => route.key === action.key */
);
/* $FlowFixMe */
console.log('backRoute =====',backRoute);
backRouteIndex = state.routes.indexOf(backRoute);
console.log('backRoute =====',backRouteIndex);
}
if (backRouteIndex == null) {
return StateUtils.pop(state);
}
if (backRouteIndex >= 0) {
return {
...state,
routes: state.routes.slice(0, backRouteIndex+1),
index: backRouteIndex - 1 + 1,
};
}
}
感谢群友conan
的贡献,将源码改成上面的样子,就可以使用goBack()
返回指定页面了,这样的优点不言而喻,但缺点就是每次调用goBack()
,如果只是简单的返回上一页需要加上null
参数,类似这样goBack(null)
,
如果这样修改,在滑动返回的时候,会有很大几率让项目卡死,请注意使用该方法,推荐集成redux。
关于快速点击会导致多次跳转的问题解决办法
感谢群友编程大叔
的贡献,如果想解决快速点击跳转的问题,需要修改部分源码。
修改react-navigation目录下,scr文件夹中的addNavigationHelpers.js文件
,可以直接替换成下面的文本,也可以查看原版链接
export default function(navigation: NavigationProp) {
// 添加点击判断
let debounce = true;
return {
...navigation,
goBack: (key?: ?string): boolean =>
navigation.dispatch(
NavigationActions.back({
key: key === undefined ? navigation.state.key : key,
}),
),
navigate: (routeName: string,
params?: NavigationParams,
action?: NavigationAction,): boolean => {
if (debounce) {
debounce = false;
navigation.dispatch(
NavigationActions.navigate({
routeName,
params,
action,
}),
);
setTimeout(
() => {
debounce = true;
},
500,
);
return true;
}
return false;
},
/**
* For updating current route params. For example the nav bar title and
* buttons are based on the route params.
* This means `setParams` can be used to update nav bar for example.
*/
setParams: (params: NavigationParams): boolean =>
navigation.dispatch(
NavigationActions.setParams({
params,
key: navigation.state.key,
}),
),
};
}
安卓上,使用TextInput的时候会让TabBar顶起来的解决办法
最简单的解决办法就是在android
目录中,添加一句话
目录:android/app/src/main/AndroidManifest.xml
中,添加
android:windowSoftInputMode="stateAlwaysHidden|adjustPan|adjustResize"
ps:在iOS下如果想一劳永逸的解决键盘问题,请使用IQKeyBoardManager
。
API
createSwitchNavigator
SwitchNavigator
的目的是一次只显示一个屏幕。默认情况下,它不处理回退操作,并在您切换时将路由重置为默认状态。这是我们从登录流程(包含注册,登录,忘记密码等)到主屏幕的必要流程。这个方法在1.x中叫做
SwitchNavigator
,在2.x中统一命名为createSwitchNavigator
createSwitchNavigator(RouteConfigs, SwitchNavigatorConfig);
RouteConfigs
路由的配置表,详细配置可以参考下面的
createStackNavigator
SwitchNavigatorConfig
SwitchNavigator
属性
-
initialRouteName
- 第一次加载时初始选项卡路由的routeName。 -
resetOnBlur
- 切换离开屏幕时,重置所有嵌套导航器的状态。默认为true
。 -
paths
- 提供routeName
到path
的深度链接,它会覆盖RouteConfigs
中设置的路径。 -
backBehavior
- 后退按钮是否会导致标签切换到初始路由?如果是,则设置为initialRoute
,否则none
。默认为none
。
export default createSwitchNavigator(
{
AuthLoading: AuthLoadingScreen,
App: AppStack,
Auth: AuthStack,
},
{
initialRouteName: 'AuthLoading',
}
);
createStackNavigator
配置路由属性和参数
这个方法在1.x中叫做
StackNavigator
,在2.x中统一命名为createSwitchNavigator
createStackNavigator(RouteConfigs, StackNavigatorConfig);
RouteConfigs
-
screen
- 对应界面名称,是一个React
组件 -
path
- 深度链接路径,从其他App或者web跳转到该App需要设置该路径 -
navigationOptions
- 用于屏幕的默认导航选项
StackNavigatorConfig
可选的路由属性
-
initialRouteName
- 设置默认屏幕。必须为路由配置中的某个screen
。 -
initialRouteParams
- 初始路由路线的参数。 -
navigationOptions
- 用于屏幕的默认导航选项。 -
paths
- 覆盖路由配置中设置的路径的映射。
可选的视觉选项
-
mode
- 定义渲染和转换的样式-
card
- 使用标准的iOS和Android屏幕转换。这是默认属性。 -
modal
- 使屏幕从底部滑入,这是一种常见的iOS模式。只适用于iOS,对Android没有影响。
-
-
headerMode
- 定义如何呈现标题-
float
- 在屏幕更改时渲染保留在顶部的单个标题和动画。这是iOS上的常见效果。 -
screen
- 每个屏幕都附有一个标题,标题与屏幕一起淡入和淡出。这是Android上的常见效果。 -
none
- 不会显示标题。
-
-
headerTransitionPreset
- 指定标题在headerMode: float
启用时应该如何从一个屏幕切换到另一个屏幕。-
fade-in-place
- 标题组件在不移动的情况下淡入淡出,类似于iOS的Twitter,Instagram和Facebook应用程序。这是默认值。 -
uikit
- iOS的默认效果。
-
cardStyle
- 使用此道具覆盖或扩展堆栈中单个卡的默认样式。-
transitionConfig
- 函数返回与默认屏幕转换合并的对象(查看类型定义中的TransitionConfig )。提供的函数将传递以下参数:-
transitionProps
- 新屏幕的过渡转换。 -
prevTransitionProps
- 旧屏幕的过渡转换。 -
isModal
- 指定屏幕是否为模态。
-
onTransitionStart
- 跳转动画即将开始时要调用的函数。onTransitionEnd
- 跳转动画完成后调用的函数。
navigationOptions
导航页面的属性和方法
title
- 可用作的headerBackTitle
的标题。此外,将用作tabBarLabel
(如果嵌套在TabNavigator中)或drawerLabel
(如果嵌套在DrawerNavigator中)的回退标题。header
- 返回一个React
元素,用来作为标题。设置null
会隐藏标题。headerTitle
- 可以传入字符串,React Element
,React Component
。默认是用上面的title
作为标题。当使用Component
时,它接受allowFontScaling
,style
和children
作为属性。title
会被放在children
中。headerTitleAllowFontScaling
- 标题字体是否应该缩放以遵循系统设置。默认值为true。headerBackImage
- 接受React Element
或者Component
用来显示自定义的后退按钮中的图片。当使用组件时,它会得到(tintColor,title)
参数。默认为react-navigation/views/assets/back-icon.png
路径下的图片,这是区分平台的默认图标。headerBackTitle
- iOS上后退按钮使用的文字,传递null
会禁用标签。默认为前一场景headerTitle
。headerTruncatedBackTitle
- 当后退按钮使用的标题字符串headerBackTitle
不适合屏幕时(比如说文字过长),会默认显示Back
。headerRight
- 接受React Element
将会显示在标题的右侧。headerLeft
- 接受React Element
或者React Component
将会显示在标题的左侧。当传递一个组件的时候,会得到(onPress,title,titleStyle
还有更多,请参考Header.js
以获得完整的列表)。headerStyle
- 标题的样式headerForceInset
- 允许将forceInset对象传递给标题中,使用的内部SafeAreaView。headerTitleStyle
- 标题组件的样式headerBackTitleStyle
- 标题上后退按钮文字样式headerTintColor
- 标题组件的色调headerPressColorAndroid
- 材质纹波的颜色(仅限Android> = 5.0)headerTransparent
- 默认为false
。如果为true
标题将没有背景,除非你明确提供了headerStyle
或headerBackground
。headerBackground
- 将此与headerTransparent一起使用,以提供一个组件在标题的背景中呈现。例如,您可以将其用于模糊视图,以创建半透明标题。gesturesEnabled
- 是否可以使用手势来返回到上一页。在iOS上默认为true
,在Android上为false
。-
gestureResponseDistance
- 用于覆盖触摸从屏幕边缘开始识别手势的距离的对象。它具有以下属性:-
horizontal
- number - 水平方向的距离。默认为25。 -
vertical
- number - 垂直方向的距离。默认为135。
-
gestureDirection
- 传递字符串用来覆盖关闭手势的方向。default
为正常行为或inverted
从右到左滑动。
Navigator Props
由StackNavigator(...)创建的导航器组件采用以下道具:
-
screenProps
- 将其他选项传递给子屏幕
createTabNavigator
createTabNavigator
已弃用。请改用createBottomTabNavigator
和/或createMaterialTopTabNavigator
。
createBottomTabNavigator
屏幕底部的简单标签栏,可让您在不同路由之间切换。路由是被懒惰初始化的 - 它们的屏幕组件直到第一次选中时才会初始化。
这个方法在1.x中叫做
TabNavigator
,在2.x中统一命名为createBottomTabNavigator
createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig);
RouteConfigs
属性请参考
createStackNavigator
。
它的navigationOptions
和createStackNavigator
不一样,下面会有说明。
BottomTabNavigatorConfig
initialRouteName
- 第一次加载时初始选项卡路由的routeName。order
- 定义选项卡顺序的routeNames数组。paths
- 提供routeName
到path
的深度链接,它会覆盖RouteConfigs
中设置的路径。backBehavior
- 后退按钮是否会导致标签切换到初始路由?如果是,则设置为initialRoute
,否则none
。默认为initialRoute
。tabBarComponent
- Options,覆盖用作标签栏的组件。-
tabBarOptions
- 标签栏具有如下属性:-
activeTintColor
- 活动选项卡的标签和图标颜色。(选中) -
activeBackgroundColor
- 活动选项卡的背景颜色。(选中) -
inactiveTintColor
- 非活动选项卡的标签和图标颜色。(未选中) -
inactiveBackgroundColor
- 非活动选项卡的背景颜色。(未选中) -
showLabel
- 是否显示标签,默认为true
。 -
style
- 标签栏的样式。 -
labelStyle
- 标签栏文字的样式。 -
tabStyle
- 选项卡的样式。 -
allowFontScaling
- 标题字体是否应该缩放以遵循系统设置。默认值为true。
-
navigationOptions
标签栏的属性和方法
title
- 通用标题可以用作headerTitle
和tabBarLabel
。tabBarVisible
- 显示或隐藏底部标签栏,默认为true
,不隐藏。tabBarIcon
-React Element
或给定{focused:boolean,tintColor:string}
的函数返回一个React.Node
,用来显示在标签栏中。tabBarLabel
- 接收字符串、React Element
或者给定{focused:boolean,tintColor:string}
的函数返回一个React.Node
,用来显示在标签栏中。如果未定义,会使用title
作为默认值。如果想要隐藏,可以参考上面的tabBarOptions.showLabel
。tabBarOnPress
- 标签栏点击事件回调,接受一个对象,其中包含如下:
[图片上传失败...(image-d10d-1535967589937)]
tabBarOnPress: async (obj: any) => {
console.log(obj);
try {
const userData = await AsyncStorage.getItem('USER_INFO');
if (userData) {
obj.defaultHandler();
}
else {
obj.navigation.navigate('Login');
}
} catch (e) {
Toast.show(e.message, 'center', 1000);
}
}
createMaterialTopTabNavigator
实现了类似
react-native-scrollable-tab-view
的左右滚动效果,但每个tab页是没有懒加载的,就是说,当使用这个生成导航的时候,每个页面都会初始化,对内存影响较大。
这个导航是基于react-native-tab-view
实现的,如果有需要可以研究。
createMaterialTopTabNavigator(RouteConfigs, TabNavigatorConfig);
RouteConfigs
属性请参考
createStackNavigator
。
TabNavigatorConfig
initialRouteName
- 第一次加载时初始选项卡路由的routeName。order
- 定义选项卡顺序的routeNames数组。paths
- 提供routeName
到path
的深度链接,它会覆盖RouteConfigs
中设置的路径。backBehavior
- 后退按钮是否会导致标签切换到初始路由?如果是,则设置为initialRoute
,否则none
。默认为initialRoute
。swipeEnabled
- 是否允许在标签之间滑动。animationEnabled
- 改变标签时是否使用动画。configureTransition
- 给定currentTransitionProps和nextTransitionProps返回一个描述选项卡之间动画的配置对象的函数。initialLayout
- 包含初始height
和可选对象width
,可以传递以防止react-native-tab-view
出现一帧的延迟。tabBarComponent
- Options,覆盖用作标签栏的组件。-
tabBarOptions
- 标签栏具有如下属性:-
activeTintColor
- 活动选项卡的标签和图标颜色。(选中) -
inactiveTintColor
- 非活动选项卡的标签和图标颜色。(未选中) -
showIcon
- 是否显示标签图标,默认为false
。 -
showLabel
- 是否显示标签,默认为true
。 -
upperCaseLabel
- 是否使标签大写,默认为true
。 -
pressColor
- 纹波的颜色(仅限Android> = 5.0)。 -
pressOpacity
- 按下标签的不透明度(仅iOS和Android <5.0)。 -
scrollEnabled
- 是否启用可滚动标签。 -
tabStyle
- 选项卡的样式。 -
indicatorStyle
- 选项卡指示符的样式(选项卡底部线的颜色)。 -
labelStyle
- 标签栏文字的样式。 -
iconStyle
- 选项卡图标的样式。 -
style
- 标签栏的样式。 -
allowFontScaling
- 标题字体是否应该缩放以遵循系统设置。默认值为true
。
-
navigationOptions
-
title
- 通用标题可以用作headerTitle
和tabBarLabel
。 -
swipeEnabled
- 如果未设置,则遵循TabNavigatorConfig
选项swipeEnabled
。启用或禁用标签之间的滑动操作为true
或false
。 -
tabBarIcon
-React Element
或给定{focused:boolean,tintColor:string}
的函数返回一个React.Node
,用来显示在标签栏中。 -
tabBarLabel
- 接收字符串、React Element
或者给定{focused:boolean,tintColor:string}
的函数返回一个React.Node
,用来显示在标签栏中。如果未定义,会使用title
作为默认值。如果想要隐藏,可以参考上面的tabBarOptions.showLabel
。 -
tabBarOnPress
- 标签栏点击事件回调,接受一个对象,其中包含如下:
[图片上传失败...(image-8865d7-1535967589937)]
tabBarOnPress: async (obj: any) => {
console.log(obj);
try {
const userData = await AsyncStorage.getItem('USER_INFO');
if (userData) {
obj.defaultHandler();
}
else {
obj.navigation.navigate('Login');
}
} catch (e) {
Toast.show(e.message, 'center', 1000);
}
}
createDrawerNavigator
创建侧边栏导航,有一些坑,需要用过才知道。
createDrawerNavigator(RouteConfigs, DrawerNavigatorConfig)
RouteConfigs
属性请参考
createStackNavigator
。
DrawerNavigatorConfig
drawerWidth
- 抽屉的宽度或返回一个新的函数。drawerPosition
- 抽屉出现的方向left
或right
,默认left
。contentComponent
- 用于呈现抽屉内容的组件,例如导航项。接收navigation
抽屉的属性。默认为DrawerItems
。有关更多信息,请参见下文。contentOptions
- 配置抽屉内容,请参见下文。useNativeAnimations
- 启用本地动画。默认是true
。drawerBackgroundColor
- 设置抽屉的背景背景。默认是white。initialRouteName
- 第一次加载时初始选项卡路由的routeName。order
- 定义选项卡顺序的routeNames数组。paths
- 提供routeName
到path
的深度链接,它会覆盖RouteConfigs
中设置的路径。backBehavior
- 后退按钮是否会导致标签切换到初始路由?如果是,则设置为initialRoute
,否则none
。默认为initialRoute
。
contentComponent
提供自定义的抽屉效果
抽屉的默认组件是可滚动的,只包含RouteConfig中路由的链接。您可以轻松地覆盖默认组件,以向抽屉中添加页眉,页脚或其他内容。默认情况下,抽屉可滚动并支持iPhone X安全区域。如果您自定义内容,请务必将内容包装在SafeAreaView中
DrawerItems
的contentOptions
items
- 路由数组,可以修改或覆盖。activeItemKey
- 识别活动路线的key。activeTintColor
- 活动标签的标签和图标颜色。(选中)activeBackgroundColor
- 活动标签的背景颜色。(选中)inactiveTintColor
- 不活动标签的标签和图标颜色。(未选中)inactiveBackgroundColor
- 不活动标签的背景颜色。(未选中)onItemPress(route)
- 按下某个Item时调用的函数。itemsContainerStyle
- item内容的样式。itemStyle
- 单个Item
样式,其中可以包含图标和标签。labelStyle
- 当标签是字符串时,会覆盖文字的样式。activeLabelStyle
- 当标签是字符串时,会覆盖选中的文字样式。inactiveLabelStyle
- 当标签是字符串时,会覆盖未选中的文字样式。iconContainerStyle
- 用来覆盖icon的样式
Screen Navigation Options
title
- 通用标题可以用作headerTitle
和tabBarLabel
。drawerLabel
- 可以传入字符串,React Element或给定{focused:boolean,tintColor:string}
的函数返回一个React.Node
,用来显示在抽屉边栏中。当不设置时,默认使用title
。drawerIcon
- React Element或给定{focused:boolean,tintColor:string}
的函数返回一个React.Node
,用来显示在抽屉边栏中。drawerLockMode
- 指定抽屉的锁定模式。这也可以通过在顶级路由器上使用screenProps.drawerLockMode动态更新。
enum('unlocked', 'locked-closed', 'locked-open')
createMaterialBottomTabNavigator
createMaterialBottomTabNavigator
这个方法在2.0正式版中被砍掉了,但官方文档没有更新,如果喜欢material
风格,可以参考react-native-material-bottom-navigation
常用属性方法
这部分会分为
createStackNavigator
和createDrawerNavigator
两部分,因为它们属性不太一样。
createStackNavigator
常用方法
[图片上传失败...(image-c747f-1535967589936)]
在新版的
react-navigation
中实现了很多常用的api,比如说push
,pop
,popToTop
等常用方法,在本文中会将属性和使用方法简单说明。
NavigationActions
-
Navigate
- 用来跳转到其他路由的方法-
routeName
- String - 必须 - 在RouteConfigs
中注册过的路由名称 -
params
- Object - 可选 - 传递的参数 -
action
- Object - 可选 - (高级)如果屏幕是导航器,则在子路由器中运行的子操作。本文档中描述的任何一项操作都可以设置为子操作。 -
key
- String - 可选 - 要导航到的路线的标识符。如果它已经存在,则返回到此路线。
-
import { NavigationActions } from 'react-navigation';
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',
params: {},
action: NavigationActions.navigate({ routeName: 'SubProfileRoute' }),
});
this.props.navigation.dispatch(navigateAction);
-
Back
- 用来返回到上一个路由或其他路由-
Key
- String | null - 如果设置,导航将从给定的键返回。如果为空,导航将返回到上一级。
-
import { NavigationActions } from 'react-navigation';
const backAction = NavigationActions.back({
key: 'Profile',
});
this.props.navigation.dispatch(backAction);
SetParams
在调用SetParams时,路由器将产生一个新的状态,该状态已经改变了由
key
标识的特定路由参数
* `params` - Object - 可选 - 新的参数被合并到现有的路径参数中。
* `key` - String - 必须 - 获取新参数的路由键。
import { NavigationActions } from 'react-navigation';
const setParamsAction = NavigationActions.setParams({
params: { title: 'Hello' },
key: 'screen-123',
});
this.props.navigation.dispatch(setParamsAction);
-
Reset
- 重置路由
Reset
操作将重置整个导航状态并将其替换为新的导航。
* `index` - number - 必须 - 导航中`routes`活动路由的索引`state`。
* `actions` - array - 必须 - 将替换导航数组。
* `key` - string | null - 可选 - 如果设置,具有给定键的导航器将重置。如果为null,则根导航器将被重置。
import { StackActions, NavigationActions } from 'react-navigation';
const resetAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Profile' })],
});
this.props.navigation.dispatch(resetAction);
-
Replace
- 用新的route替换当前的route
Replace操作将给定
key
上的路线替换为另一条路线。
* `key` - string - 必须 - 要替换路由的`key`。
* `newKey` - string - 用于替换路由的`key`。如果未提供,则自动生成。
* `routeName` - string - 用于替换路由的`routeName`。
* `params` - object - 要传入替换路由的参数。
* `action` - object - 可选的子操作。
-
Push
- 入栈
Push
操作会在堆栈顶部添加一条路径并向前导航。这与之前的不同之处在于,如果某个组件已经存在路由中,navigate
则会弹出到堆栈中的较早版本。Push
将始终添加在顶部,因此可以多次安装组件。
* `routeName` - string - 要跳转路由的`routeName`。
* `params` - object - 传递的参数,可以通过(this.props.navigation.state.params)找到。
* `action` - 子操作。
-
pop(n)
- 出栈
Pop
操作将使您回到堆栈中的前一个屏幕。n
参数允许您指定要多少个屏幕出栈。
* `n` - number - 要出栈的屏幕数量。
-
PopToTop
- 回到栈顶
PopToTop
操作会将您带回堆栈中的第一个屏幕,解除所有其他屏幕。它的功能与StackActions.pop({n: currentIndex})
类似。
----------------------------------------------新老版本的分割线--------------------------------------------------------
screenProps
之前是没有介绍这个属性的,但经过这么久发现,很多人都不知道这个属性,不知道它能干嘛,在这里我就简单的介绍下
screenProps
:react-navigation自带的一个属性,属于navigationOptions
的一个属性,可以全局控制navigationOptions
中的某些值,比如说你想做换肤功能,修改这个属性绝对是最简单的方式。
// 假设App就是项目中的入口文件,如果还不知道,可以看下Demo,在这里我将主题色通过screenProps属性修改成'red'
// 在页面中就可以通过screenProps来直接改变了,这个在Demo
中的Test2里面
static navigationOptions = ({navigation,screenProps}) => ({
// 这里面的属性和App.js的navigationOptions是一样的。
headerStyle:{backgroundColor:screenProps?
screenProps.themeColor:
'#4ECBFC'},
)
})
StackNavigator 基础用法/属性介绍
const MyApp = StackNavigator({
// 对应界面名称
MyTab: {
screen: MyTab,
},
Detail: {
screen: Detail,
navigationOptions:{
headerTitle:'详情',
headerBackTitle:null,
}
},
}, {
headerMode: 'screen',
});
导航配置
screen
:对应界面名称,需要填入import
之后的页面。
navigationOptions
:配置StackNavigator的一些属性。
-
title
:标题,如果设置了这个导航栏和标签栏的title就会变成一样的,所以不推荐使用这个方法。 -
header
:可以设置一些导航的属性,当然如果想隐藏顶部导航条只要将这个属性设置为null
就可以了。 -
headerTitle
:设置导航栏标题,推荐用这个方法。 -
headerBackTitle
:设置跳转页面左侧返回箭头后面的文字,默认是上一个页面的标题。可以自定义,也可以设置为null
-
headerTruncatedBackTitle
:设置当上个页面标题不符合返回箭头后的文字时,默认改成"返回"。(上个页面的标题过长,导致显示不下,所以改成了短一些的。) -
headerRight
:设置导航条右侧。可以是按钮或者其他。 -
headerLeft
:设置导航条左侧。可以是按钮或者其他。 -
headerStyle
:设置导航条的样式。背景色,宽高等。如果想去掉安卓导航条底部阴影可以添加elevation: 0
,iOS下用shadowOpacity: 0。 -
headerTitleStyle
:设置导航条文字样式。安卓上如果要设置文字居中,只要添加alignSelf:'center'
就可以了。在安卓上会遇到,如果左边有返回箭头导致文字还是没有居中的问题,最简单的解决思路就是在右边也放置一个空的按钮。
在最新版本的react-navigation
中,安卓居中可以使用 flex:1, textAlign: 'center'
来实现。
-
headerBackTitleStyle
:设置导航条返回文字样式。 -
headerTintColor
:设置导航栏文字颜色。总感觉和上面重叠了。 -
headerPressColorAndroid
:安卓独有的设置颜色纹理,需要安卓版本大于5.0 -
gesturesEnabled
:是否支持滑动返回手势,iOS默认支持,安卓默认关闭 -
gestureResponseDistance
:对象覆盖触摸从屏幕边缘开始的距离,以识别手势。 它需要以下属性:- horizontal - number - 水平方向的距离 默认为25。
- vertical - number - 垂直方向的距离 默认为135。
// 设置滑动返回的距离
gestureResponseDistance:{horizontal:300},
注:beta13新出的东西,挺有意思,以后可以手动控制返回了
导航视觉效果
mode
:定义跳转风格。
-
card
:使用iOS和安卓默认的风格。 -
modal
:iOS独有的使屏幕从底部画出。类似iOS的present效果
headerMode
:边缘滑动返回上级页面时动画效果。
-
float
:iOS默认的效果,可以看到一个明显的过渡动画。 -
screen
:滑动过程中,整个页面都会返回。 -
none
:没有动画。
cardStyle
:自定义设置跳转效果。
transitionConfig
: 自定义设置滑动返回的配置。
onTransitionStart
:当转换动画即将开始时被调用的功能。
onTransitionEnd
:当转换动画完成,将被调用的功能。
path
:路由中设置的路径的覆盖映射配置。
initialRouteName
:设置默认的页面组件,必须是上面已注册的页面组件。
initialRouteParams
:初始路由的参数。
path
:path属性适用于其他app或浏览器使用url打开本app并进入指定页面。path属性用于声明一个界面路径,例如:【/pages/Home】。此时我们可以在手机浏览器中输入:app名称://pages/Home来启动该App,并进入Home界面。
TabNavigator 基础用法/属性介绍
const MyTab = TabNavigator({
ShiTu: {
screen: ShiTu,
navigationOptions:{
tabBarLabel: '识兔',
tabBarIcon: ({tintColor}) => (
),
},
}, {
tabBarPosition: 'bottom',
swipeEnabled:false,
animationEnabled:false,
tabBarOptions: {
style: {
height:49
},
activeBackgroundColor:'white',
activeTintColor:'#4ECBFC',
inactiveBackgroundColor:'white',
inactiveTintColor:'#aaa',
showLabel:false,
}
});
屏幕导航配置
screen
:和导航的功能是一样的,对应界面名称,可以在其他页面通过这个screen传值和跳转。
navigationOptions
:配置TabNavigator的一些属性
-
title
:标题,会同时设置导航条和标签栏的title,还是不推荐这种方式。 -
tabBarVisible
:是否隐藏标签栏。默认不隐藏(true) -
tabBarIcon
:设置标签栏的图标。需要给每个都设置。 -
tabBarLabel
:设置标签栏的title。推荐这个方式。 -
tabBarOnPress
:设置tabBar的点击事件,内部提供了两个属性,一个方法(obj)。
beta13新添加的方法,使用方式有些奇葩,如果想要使用,请参照下面的代码
tabBarOnPress:(obj)=>{
console.log(obj);
obj.jumpToIndex(obj.scene.index)
},
标签栏配置
tabBarPosition
:设置tabbar的位置,iOS默认在底部,安卓默认在顶部。(属性值:'top','bottom')
swipeEnabled
:是否允许在标签之间进行滑动。
animationEnabled
:是否在更改标签时显示动画。
lazy
:是否根据需要懒惰呈现标签,而不是提前制作,意思是在app打开的时候将底部标签栏全部加载,默认false,推荐改成true哦。
initialRouteName
: 设置默认的页面组件
backBehavior
:按 back 键是否跳转到第一个Tab(首页), none 为不跳转
tabBarOptions
:配置标签栏的一些属性
iOS属性
-
activeTintColor
:label和icon的前景色 活跃状态下(选中)。 -
activeBackgroundColor
:label和icon的背景色 活跃状态下(选中) 。 -
inactiveTintColor
:label和icon的前景色 不活跃状态下(未选中)。 -
inactiveBackgroundColor
:label和icon的背景色 不活跃状态下(未选中)。 -
showLabel
:是否显示label,默认开启。 -
style
:tabbar的样式。 -
labelStyle
:label的样式。
安卓属性
-
activeTintColor
:label和icon的前景色 活跃状态下(选中) 。 -
inactiveTintColor
:label和icon的前景色 不活跃状态下(未选中)。 -
showIcon
:是否显示图标,默认关闭。 -
showLabel
:是否显示label,默认开启。 -
style
:tabbar的样式。 -
labelStyle
:label的样式。 -
upperCaseLabel
:是否使标签大写,默认为true。 -
pressColor
:material涟漪效果的颜色(安卓版本需要大于5.0)。 -
pressOpacity
:按压标签的透明度变化(安卓版本需要小于5.0)。 -
scrollEnabled
:是否启用可滚动选项卡。 -
tabStyle
:tab的样式。 -
indicatorStyle
:标签指示器的样式对象(选项卡底部的行)。安卓底部会多出一条线,可以将height
设置为0来暂时解决这个问题。 -
labelStyle
:label的样式。 -
iconStyle
:图标的样式。
ps:很多人问我,为什么安卓上的tabbar文字会下移, 是因为安卓比iOS多了一个属性,就是iconStyle
,通过设置labelStyle
和iconStyle
两个样式,外加style
的高度,来使效果更佳合理.