做应用肯定不可能就一个界面,所以这里涉及到我们界面跳转的问题,那RN是怎么利用导航器来实现跳转的呢?我们结合官网给出的例子进行分析,后面笔者发现其实RN的某些思路其实跟Android大同小异,如果你对Android的启动模式有了解还有Android的栈的理解,我相信理解这个应该不会很复杂 D)
首先如果想用react-navigation就要先安装它,react-navigation在React Native项目中安装。所以我们需要cmd指令进入项目文件夹之后进行如下命令:
npm install --save react-navigation 下载react-navigation
接下来,安装react-native-gesture-handler
npm install --save react-native-gesture-handler
链接所有本机依赖项
react-native link react-native-gesture-handler
ios的同学就不需要这么做了……
要完成针对Android的react-native-gesture-handler的安装,请务必对以下内容进行必要的修改MainActivity.java
:
<pre style="box-sizing: inherit; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; margin: 16px 0px 14px; padding: 14px 15px 12px; border-radius: 3px; border: none; display: block; line-height: 1.6; background: rgb(246, 246, 246); color: rgb(61, 70, 77); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivityDelegate; import com.facebook.react.ReactRootView; import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
public class MainActivity extends ReactActivity {
*/**
* ** Returns the name of the main component registered from JavaScript.* ** This is used to schedule rendering of the component.* **/*@Override
protected String getMainComponentName() {
return "NavigationDemo";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Override
protected ReactRootView createRootView() {
return new RNGestureHandlerEnabledRootView(MainActivity.this);
}
};
}
}</pre>
到此就可以安心的使用react-navigation了,本人之前没有这样的步骤去做,所以出现了几次问题,切记一定要按照这样的步骤去安装!
范例解析:
<pre style="box-sizing: inherit; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; margin: 16px 0px 14px; padding: 14px 15px 12px; border-radius: 3px; border: none; display: block; line-height: 1.6; background: rgb(246, 246, 246); color: rgb(61, 70, 77); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import React from 'react'; import { Button, View, Text } from 'react-native'; import { createStackNavigator, createAppContainer } from 'react-navigation'; // Version can be specified in package.json
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => this.props.navigation.navigate('Details')}
/>
</View>
);
}
}
class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details"
//这里的push相当于跳转的时候不管当前栈里有没有该实例都会重新创建一个新的
onPress={() => this.props.navigation.push('Details')}
/>
</View>
);
}
}
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}</pre>
这里先贴出来代码范例
其实有点基础的不难看出来,程序的入口是在App并且返回渲染了AppContainer的对象,并且这个对象通过createAppContainer返回StackNavigation,对于createAppContainer这个方法网上没有太多的资料,打开源码解释如下:
Create an app container to wrap the root navigator
创建一个应用程序容器来包装根导航器
字面上的理解比较容易就是创建一个容器来承载StackNavigation导航器,那这个导航器是什么?
代码里面分两个部分,第一个部分是包含所有界面的组件集合,另一个部分是声明我们初始化的界面组件是哪一个,看到这里我们应该知道了,范例中我们声明了两个界面组件,Home 和 Details ,并且声明初始化的路由名字是Home,所以打开界面的首先会进入Home界面,其实这有点像注册路由一样,我们要把设计到的界面组件注册到路由里面,这样我们才会navigation的时候才会找得到它。
该范例运行结果如下:
我们看到当前的界面确实是Home Screen,并且点击按钮会打开Details界面,返回箭头会直接返回Home,这只是一个简单的跳转逻辑,我们需要做一些更改,怎么改呢?我们可以尝试一下在Details Screen里面再放入一下Button,细心地朋友看到了上面代码中我们已经加入了,并且跳转的时候我们还是跳转到当前并且是push的,效果会怎么样呢,我已经给了注释,结果却是会重新打开这个Derails界面,此时的栈中就两个Details实例了,这是不是跟Android的启动模式相似呢,安卓默认的启动模式standard就是这样的效果,但是如果我们不用push,还是navigation的话,结局是什么样呢?结果就是没有任何反应,那Android的启动模式可以做到类似的效果,唯一的不同点就是Android会走特定的生命周期方法。
goBack
堆栈导航器提供的标题将在可以从活动屏幕返回时自动包含后退按钮(如果导航堆栈中只有一个屏幕,则没有任何内容可以返回,因此没有返回键)。
有的时候我们希望能够主动触发此行为,我们就可以使用this.props.navigation.goBack();
。
<pre style="box-sizing: inherit; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 13px; word-break: initial; overflow-wrap: initial; white-space: pre; overflow: auto; margin: 16px 0px 14px; padding: 14px 15px 12px; border-radius: 3px; border: none; display: block; line-height: 1.6; background: rgb(246, 246, 246); color: rgb(61, 70, 77); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">class DetailsScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.push('Details')}
/>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</View>
);
}
}</pre>
这里面我们发现回到Home我们是直接navigation的,看看效果是不是跟Android的启动模式SingleTask很类似呢,对,就是这样,那我们也可以另外一种方式也可以达到这个效果navigation.popToTop()。
传递参数
导航跳转我们搞定了,接下来我们要传递参数,界面与界面之间传递参数是必不可少的操作。
传递参数是在我们navigation的时候多加一个参数即可,this.props.navigation.navigate('routeName',{key:value}),格式就是这样,我们看一下代码:
这里我们只是传递了两个参数itemId和otherParam,那在DetailsScreen我们怎么去接收呢,代码如下:
其实方式很简单,跟map的操作方式很像。
如果你想通过道具直接访问params(例如。this.props.itemId
)而不是this.props.navigation.getParam
,那么你可以使用社区开发的react-navigation-props-mapper包。
配置标题栏
现在看我们的界面是不是很枯燥无味,导航栏上面什么也没有,这个时候我们可以添加我们自己的界面标题。
这个时候我们需要使用到navigationOptions这个属性来配置标题显示。
如上图所示的配置即可,然后运行我们会发现标题有了:
createStackNavigator 默认情况下使用平台约定,因此在iOS上标题将居中,而在Android上它将是左对齐的。
网友评论