六、react-navigation记录


1. 集成了react-navigation后,会发现界面背景色变化了。参考官网说明:

1
If you run this code, you will see a screen with an empty navigation bar and a grey content area containing your HomeScreen component.

也就是说react-navigation会给界面添加默认的grey背景色,会导致列表界面有间隔线的会非常不明显。还有TextInput的hint也不明显。要取消该style应如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const AppRoutes = createStackNavigator({
PublicFeelingsDetailPage: { screen: PublicFeelingsDetailPage },
Wifi: { screen: Wifi },

}, {
headerMode: 'none',//隐藏导航栏,也就是android的ToolBar
initialRouteName: 'PublicFeelingsDetailPage',
cardStyle: {
backgroundColor: 'transparent',
},
});

export default class Root extends Component{

render(){
return <AppRoutes />;
}
}
关键代码:
cardStyle: {
backgroundColor: 'transparent',
}


2. react-navigation 配置了多个页面后,会用 initialRouteName 来声明哪个页面是 first page或初始页面。那我碰到问题是如何给这个初始页面传递参数呢?

我们都知道,尽管有了react native, 但是android app 不可能做到用纯 react native来开发。这种场景下一个android app由android原生,react native 这2个系统组成。
其中 react natvie开发的页面关系由 react navigation管理。两个系统总要交互吧? 由android页面跳转到 react native页面,并且android原生要传递参数过去,react navigation的默认首页面该如何获取到由android传递过来的参数值呢? 上代码:

MyRouter.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import React, { Component } from 'react'
import TaskDetailPage from './TaskDetailPage';
import TaskFeedbackPage from './TaskFeedbackPage';
import {createStackNavigator} from 'react-navigation';
import StackViewStyleInterpolator from 'react-navigation-stack/dist/views/StackView/StackViewStyleInterpolator'

export default class MyRouter extends Component {

render() {

const AppRoutes = createStackNavigator({

TaskDetailPage: { screen: TaskDetailPage },
TaskFeedbackPage: { screen: TaskFeedbackPage }

}, {
headerMode: 'none',//隐藏导航栏,也就是android的ToolBar
initialRouteName: 'TaskDetailPage',
initialRouteParams: {...this.props, navTitle: '任务详情', androidNativeFinish: true},
transitionConfig: ()=>({
screenInterpolator:StackViewStyleInterpolator.forHorizontal
}),
cardStyle: {
backgroundColor: 'transparent',
},
});
return <AppRoutes />;
}
}

只要将 createStackNavigator 代码块丢到 render方法中定义, 就可以在 initialRouteParams 里使用 this.props,从而 默认首页 TaskDetailPage就可以获取到值了。


3. 我们聊一聊单入口实现方式。 用rn 做了2个功能模块:

task(任务管理)模块有3个页面: TaskListPage, TaskCreatePage, TaskDetailPage . TaskListPage是列表页面, TaskCreatePage是新增任务页面, TaskDetailPage是任务详情页面。
meeting(会议管理)模块也有如上3个页面: MeetingListPage, MeetingCreatePage, MeetingDetailPage。
task模块和 meeting模块 都是由原生端点击进入的。那么我们会建立2个 react navigation来管理各自模块。
TaskRouter.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const AppRoutes = createStackNavigator({

TaskListPage: { screen: TaskListPage },
TaskCreatePage: { screen: TaskCreatePage },
TaskDetailPage: { screen: TaskDetailPage }

}, {
headerMode: 'none',//隐藏导航栏,也就是android的ToolBar
initialRouteName: 'TaskListPage',
transitionConfig: ()=>({
screenInterpolator:StackViewStyleInterpolator.forHorizontal
}),
cardStyle: {
backgroundColor: 'transparent',
},
});

export default class TaskRouter extends Component {

render() {
return <AppRoutes />;
}

}

MeetingRouter.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const AppRoutes = createStackNavigator({

MeetingListPage: { screen: MeetingListPage },
MeetingCreatePage: { screen: MeetingCreatePage },
MeetingDetailPage: { screen: MeetingDetailPage }

}, {
headerMode: 'none',//隐藏导航栏,也就是android的ToolBar
initialRouteName: 'MeetingListPage',
transitionConfig: ()=>({
screenInterpolator:StackViewStyleInterpolator.forHorizontal
}),
cardStyle: {
backgroundColor: 'transparent',
},
});

export default class MeetingRouter extends Component {

render() {
return <AppRoutes />;
}
}

TaskRouter 和 MeetingRouter 各自托管了自身的页面。他们是入口。android原生只要跳转到 TaskRouter 或 MeetingRouter页面即可。
那是否需要在android端还得要建立两个Activity分别对应 TaskRouter 和 MeetingRouter呢?显然不应该这样用。否则rn每建立个入口。android原生端都要新建对应类,又要编译apk,就违背了rn初衷了嘛。
我们建立一个叫 PageActivity的类,负责进入所有的rn入口端:

PageActivity.kt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import android.os.Bundle
import com.facebook.react.ReactActivityDelegate
class PageActivity : ReactActivity() {

override fun getMainComponentName(): String? {
return "PageActivity"
}

override fun createReactActivityDelegate(): ReactActivityDelegate {

return object : ReactActivityDelegate(this, mainComponentName) {
override fun getLaunchOptions(): Bundle? {
return intent.extras
}
}
}
}

getLaunchOptions允许 intent可以带参数。再看看rn端

index.js

1
2
3
import { AppRegistry } from 'react-native';
import PageEntry from './js/page/PageEntry';
AppRegistry.registerComponent('PageActivity', () => PageEntry);

可以看到,android原生端跳转到 PageActivity类实际上是进入到 PageEntry页面。

PageEntry.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React, { Component } from 'react';
import CaseRouter from './case/CaseRouter';
import CaseCoworkRouter from './casecowork/CaseCoworkRouter';
import PoliceRouter from './police/PoliceRouter';
import TaskRouter from './task/TaskRouter';
import SimpleTaskRouter from './simpletask/SimpleTaskRouter';
import KeyPersonRouter from './keyperson/KeyPersonRouter';
import MyTodoRouter from './mytodo/MyTodoRouter';
import SimpleTaskDetailPage from './simpletask/SimpleTaskDetailPage';
import SimpleTaskDetailRouter from './simpletask/SimpleTaskDetailRouter';

export default class PageEntry extends Component {
render() {
if (!this.props.name) return null;
switch (this.props.name) {
case 'Task'://指挥管理
return <TaskRouter />;
case 'Meeting'://任务管理(柳州的内部管理app,简化版的指挥管理)
return <MeetingRouter />
}
}
}

看到了木有? 只要原生跳转到 PageActivity 时带 Task 就可以展示 TaskRouter,带 Meeting参数 就可以 展示 MeetingRouter。
原生端跳转代码如下:

1
2
3
4
val intent = Intent(context, PageActivity::class.java).apply { 
putExtra(“name”, "Task")
}
startActivity(this, intent)

注意:intent传入参数的key为啥是 name ? PageEntry.js里看到了 this.props.name 木有?