react-navigation 使用的整體框架 安卓物理返回鍵
阿新 • • 發佈:2018-12-11
一、"react-navigation": "^1.0.0-beta.22" 低版本的使用
建立兩個資料夾專門來寫導航的頁面
1、TabNavigator 專門來寫Tab欄上的頁面(tab欄上的每個頁面的導航都可以在元件中設定,新版本的導航會統一寫一個頁面)
import React, { Component } from 'react'; import { TabNavigator, TabBarBottom } from 'react-navigation'; import Home from '../components/Home'; import User from '../components/User'; export default (TabNav = TabNavigator({ Home: { screen: Home }, User: { screen: User }, }, { tabBarComponent: TabBarBottom, tabBarPosition: 'bottom', showIcon: true, animationEnabled: true, swipeEnabled: false, tabBarOptions: { activeTintColor: '#3D3939', inactiveTintColor: '#3D3939', }, }));
Tab欄上的每個頁面的導航
static navigationOptions = {
header: null,
title: '首頁',
tabBarIcon: ({ focused }) => (
<Image style={{ width: scaleSize(54), height: scaleSize(54) }} source={focused ? require('../../img/home-selected.png') : require('../../img/home.png')} />
),
}
2、AppNavigator 把所有跳轉的頁面都寫在此頁面裡
import Splash from '../pages/Splash'; // app開屏畫面
import TabRouter from './TabRouter'; //tab欄
import Guide from '../guide/guide'; // 引導頁
export const AppNavigator = StackNavigator(
{
Splash: { screen: Splash },
tab: { screen: TabRouter },
Guide: { screen: Guide }
}
可以再建立一個頁面專門寫安卓物理返回鍵操作(並且在tab欄上可以點選兩次退出App)
import React from 'react';
import { addNavigationHelpers, StackNavigator, NavigationActions } from 'react-navigation';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { BackHandler } from "react-native";
import { AppNavigator } from "./AppNavigator";
class App extends React.Component {
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}
onBackPress = () => {
const { dispatch, nav } = this.props;
if (nav.index === 0) {
return false;
}
dispatch(NavigationActions.back());
return true;
};
render() {
const { dispatch, nav } = this.props;
const navigation = addNavigationHelpers({
dispatch,
state: nav,
});
return <AppNavigator navigation={navigation} />;
}
}
App.propTypes = {
dispatch: PropTypes.func.isRequired,
nav: PropTypes.object.isRequired,
};
const mapStateToProps = state => ({
nav: state.nav,
});
export default connect(mapStateToProps)(App);
在安卓上可以使用物理鍵返回需要redux整合
nav頁面(儲存導航狀態)
import { NavigationActions } from 'react-navigation';
import { AppNavigator } from '../Routers/AppNavigator';
const initialState = AppNavigator.router.getStateForAction(NavigationActions.init());
// ---------reducer---------
export default function nav(state = initialState, action) {
let nextState;
if (action && action.type.indexOf('Navigation/') === 0) {
nextState = AppNavigator.router.getStateForAction(action, state);
}
return nextState || state;
}
在註冊頁面裡引用App元件,就可以實現各個頁面的導航以及安卓物理鍵的使用
二、"react-navigation": "^2.3.0" 新版本的使用
在新版本中很有屬性和方法被移除裡,使用redux整合,需要下載一個外掛react-navigation-redux-helpers
跟舊版本一樣,都是建立兩個檔案存導航頁面
1、TabNavigator 專門來寫Tab欄上的頁面
import Home from '../components/home'; // 底部:首頁
import User from '../components/user'; //底部: 我的
const Home = createStackNavigator({
Home: {
screen: Home
navigationOptions: () => ({
title: 首頁,
headerBackTitle: null,
header: null,
headerStyle: {
backgroundColor: '#ffffff',
borderBottomWidth: 0
},
headerTitleStyle: {
color: 'rgba(13,14,21,1)',
fontSize: 18
},
headerTintColor: '#000',
borderWidth: 0
})
}
});
const User = createStackNavigator({
User: {
screen: User,
navigationOptions: () => ({
title: 我的,
headerBackTitle: null,
header: null,
headerStyle: {
backgroundColor: '#ffffff',
borderBottomWidth: 0
},
headerTitleStyle: {
color: 'rgba(13,14,21,1)',
fontSize: 18
},
headerTintColor: '#000'
})
}
});
const TabBarPage = createBottomTabNavigator(
{
Home: {
screen: Home,
navigationOptions: {
tabBarLabel: ({ tintColor, focused }) => (
<Text style={{ color: tintColor, fontSize: 12, textAlign: 'center' }}>首頁</Text>
),
tabBarIcon: ({ focused, tintColor }) => <Icon name="icon-home" size={30} color={tintColor} />
),
}
},
User: {
screen: My,
navigationOptions: {
tabBarLabel: ({ tintColor, focused }) => (
<Text style={{ color: tintColor, fontSize: 12, textAlign: 'center' }}>我的</Text>
),
tabBarIcon: ({ focused, tintColor }) => <Icon name="icon-user" size={30} color={tintColor} />
),
}
}
},
{
lazy: true,
animationEnabled: true,
backBehavior: true,
tabBarPosition: 'bottom',
tabBarOptions: {
activeTintColor: '#3e9ce9',
inactiveTintColor: '#999999',
showIcon: true,
style: {
backgroundColor: '#fff',
height: 98
},
indicatorStyle: {
opacity: 0
},
tabStyle: {
padding: 0
}
}
}
);
2、AppNavigator 把所有跳轉的頁面都寫在此頁面裡(但是因為更新了版本,在redux整合的時候,做了更多的處理)
import Splash from '../pages/Splash'; // app開屏畫面
import TabRouter from './TabRouter'; //tab欄
import Guide from '../guide/guide'; // 引導頁
import { createStackNavigator } from 'react-navigation'; // 頁面切換 路由導航元件
import { reduxifyNavigator, createReactNavigationReduxMiddleware, createNavigationReducer } from 'react-navigation-redux-helpers';
export const RootNavigator = createStackNavigator(
{
Splash: { screen: Splash },
tab: { screen: TabRouter },
Guide: { screen: Guide }
}
export const middleware = createReactNavigationReduxMiddleware(
'root',
state => state.nav
)
const AppWithNavigationState = reduxifyNavigator(RootNavigator, 'root');
const mapStateToProps = state => ({
state: state.nav
});
const AppNavigator = connect(mapStateToProps)(AppWithNavigationState);
可以再建立一個頁面專門寫安卓物理返回鍵操作(並且在tab欄上可以點選兩次退出App)
import React from 'react';
import { NavigationActions } from 'react-navigation';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { BackHandler } from "react-native";
import { AppNavigator } from "./AppNavigator";
class App extends Component {
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.onBackPress);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.onBackPress);
}
onBackPress = () => {
const { dispatch, state } = this.props;
if(state.index === 0){
if(this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
Alert.alert('提示','您確定要退出嗎?',[
{text: '取消', onPress: () => {return false }},
{text: '確定', onPress: () => { BackHandler.exitApp() }}
])
}
this.lastBackPressed = Date.now();
return true
// return false;
}
dispatch(NavigationActions.back());
return true;
};
render() {
const { dispatch, nav } = this.props;
// const navigation = addNavigationHelpers(); 因為addNavigationHelpers 已被移除不存在
return <AppNavigator navigation={{
dispatch,
state: nav
}} />
}
}
export default connect(mapStateToProps)(App)
nav頁面(儲存導航狀態)這個跟舊的一樣
import { NavigationActions } from 'react-navigation';
import { AppNavigator } from '../Routers/AppNavigator';
const initialState = AppNavigator.router.getStateForAction(NavigationActions.init());
// ---------reducer---------
export default function nav(state = initialState, action) {
let nextState;
if (action && action.type.indexOf('Navigation/') === 0) {
nextState = AppNavigator.router.getStateForAction(action, state);
}
return nextState || state;
}
reducer檔案下的index頁面
import { combineReducers } from 'redux';
import nav from './nav';
export default const reducers = combineReducers({
nav
});
store檔案下的index頁面
import { createStore, applyMiddleware } from "redux";
import thunk from 'redux-thunk'
import logger from 'redux-logger'
import reducers from './reducers/index';
import { middleware } from "../containers/app";
const store = applyMiddleware(thunk, logger, middleware)(createStore)(reducers);
window.store = store;
export default store;
import { Provider, connect } from 'react-redux';
import React from 'react';
import App from './App';
import { middleware } from './AppNavigator';
import store from './store/index';
class Root extends React.Component {
render() {
return (
<Provider store={store}>
<App />
</Provider>
);
}
}