react native 實戰系列教程之Navigator實現頁面跳轉

主界面開發

上一節,我們已經完成瞭首頁的開發,現在,我們繼續完成主界面的開發,就是添加底部‘首頁’和‘我的’兩個tabbar。

在js/文件夾下,新建MainScene.js文件

import React,{Component} from 'react';
import {
    View,
    Text,
    TouchableOpacity,
    Image,
    StyleSheet,
}from 'react-native';

export default class MainScene extends Component{
    constructor(props){
        super(props);
        this.state={
            tabIndex:0,
        }

    }

    render(){
        return(
            

                
                
                    
                        
                            
                            首頁
                        
                    
                    
                        
                            
                            我的
                        
                    
                

            

        );
    }

    //tab點擊事件
    _onTabPress(index){
//console.log('index = '+ index);
        //this.viewPager.setPage(index);
        this.setState({
            tabIndex:index,
        });
    }

}
var styles = StyleSheet.create({
    ItemView:{
        flex:1,
        justifyContent:'center',
        alignItems:'center',
        marginTop:3,
    },
    TabTextSelect:{
        flex:1,
        textAlign:'center',
        alignItems:'center',
        color:'#ff5722',
    },
    TabTextUnSelect:{
        flex:1,
        textAlign:'center',
        alignItems:'center',
        color:'#d5d5d5',
    },
});

主要繪制瞭,底部兩個帶圖標的選項卡,根據state.tabIndex的索引,動態修改tab的icon和文字樣式,然後將index.android.js的啟動頁修改為MainScene,運行程序,結果如下

主界面vcztvNPE2sjd0rPD5jwvcD4NCjxwPk1haW5TY2VuZS0mZ3Q7cmVuZGVyPC9wPg0KPHByZSBjbGFzcz0=”brush:java;”>
render(){
var page = this.state.tabIndex===0?:;
return(

{page}
…//省略其它代碼

);
}

這裡我們使用動態渲染頁面的方式,當選項進行切換時,根據tabIndex索引值,獲取到對應的頁面進行顯示。

ok,添加完之後,運行,現在的效果如下

主界面

到此,主界面的功能基本完成,隻是點擊列表item沒反應,因為,我們還沒給頁面設計跳轉功能,下面我們將來說說應用的導航器。

應用導航器

關於react-native頁面跳轉和數據傳遞,使用到的是Navigator這個組件。它可以幫我們在在不同的頁面進行切換,隻要指定瞭路由,在renderScene方法就會渲染對應的頁面。更多詳細介紹

由於我們的應用要跳轉的地方會有很多,所以我們需要為APP定義一個統一的路由入口。

我們先抽出定義一個應用的導航器AppNavigator,在js/component/下新建AppNavigator.js

import React,{Component} from 'react';
import {
    Navigator,
} from 'react-native';
//應用導航器
export default class AppNavigator extends Component{
    constructor(props){
        super(props);
    }
    render(){
        return(
            {
                  let Scene = route.component;
                  return 
                }}
                style={{flex:1,}}
                configureScene={(route) => {
                  if(route.sceneConfig){
                    return route.sceneConfig;
                  }
                  return Navigator.SceneConfigs.HorizontalSwipeJump;
                }}
              />
            );
    }
}

我們指定瞭路由數據結構如下(這個數據結構根據自己的需求去定義),

{
    id:this.props.id,
    data:this.props.data,
    name:this.props.name,
    component:this.props.component
}

頁面的唯一識別id,要傳遞的數據data(可以任意類型的數據),頁面的名稱name(頁面的名稱,這裡用於TitleBar顯示標題名稱),要渲染的頁面組件component。重要的部分在於renderScene函數。

renderScene={(route,navigator)=>{
  let Scene = route.component;
  return 
}}

這裡我們獲取到route傳過來的component,然後將該component當作一個view節點返回回去,並且給該組件傳入瞭一組props,這樣在該Scene下,就可以通過this.props獲取到id\data\name\navigaror.當獲取到navigaror對象之後,我們可以進行push\pop操作,實現頁面的跳轉\回退功能。

configureScene函數是配置頁面跳轉時的動畫效果

使用導航器進行頁面跳轉

導航器寫好之後,我們就該思考將它作為應用的統一入口應該放置在哪合適。

如果你在使用Navigator過程中,碰到跳轉時,某些元素比如標題、底部的tabbar,在跳轉之後還需要特殊處理(隱藏),那麼可能是你把Navigator放的位置不夠準確。就像我之前寫的時候,將Navigator放在瞭HomeScene中,導致點擊影片item頁面跳轉之後(跳到詳情),底部的tabbar還顯示著。一開始想的是在跳轉之後將tabbar隱藏,但是這樣就會有閃動的情況,後來把Navigator位置改正之後,就達到想要的結果瞭。

既然作為程序的統一路由入口,那麼我們是不是有理由這麼想,它也應該是放在程序的啟動處。是的,將它放在index.android.js。

import AppNavigator from './js/component/AppNavigator';
import MainScene from './js/MainScene';
class XiFan extends Component {

  render(){
    return(
        
    );
  }
}

將導航器的初始路由頁面設置為MainScene,由於是主界面,所以不用傳遞data\name數據。

然後打開MainScene,修改代碼

render(){
    var page = this.state.tabIndex===0?:;
    ....//省略其它代碼
}

增加瞭navigator參數,而this.props.navigator實例對象是來至於AppNavigator的renderScene中navigator,這樣我們就把navigator實例對象傳遞給瞭HomeScene。再打開HomeScene,要修改的地方有兩處

HomeScene->render()

讓TitleBar具有返回/回退功能

將navigator對象傳遞給TitleBar


再打開TitleBarComponent ->_onIconClick()

//返回按鈕事件
_onIconClick(){
    var navigator = this.props.navigator;
    if(navigator){
        navigator.pop();
    }
}

在獲取到navigator對象後,進行pop操作,就可以返回瞭。

將navigator對象傳遞給DramaComponent


    
        
    
    
        
    

這樣DramaComponent也有瞭navigator實例對象,打開DramaComponent,我們給它item點擊事件添加跳轉到詳情的功能。

DramaComponent -> _onItemPress

//item 點擊跳轉
_onItemPress(movie){
    const navigator = this.props.navigator;
    if(navigator){
        navigator.push({
            id:'DramaDetailScene',
            data:movie,
            name:movie.name,
            component:DramaDetailScene
        });
    }
}

也就是,如果是由Navigator導航的組件,那麼該組件本身就有Navigator對象,並由this.props.navigator取得,如果是導航組件的內部組件要使用導航對象,那麼就要給該組件增加props屬性

navigator={this.props.navigator}

這裡item點擊跳轉的是詳情頁DramaDetailScene,我們先簡單的寫下這個頁面,後面在具體實現詳情頁

新建DramaDetailScene.js

import React,{Component} from 'react';
import {
    View,
    Text
} from 'react-native';
import TitleBar from './component/TitleBarComponent';
export default class DramaDetailScene extends Component{

    constructor(props) {
        super(props);
    }

    render(){
        return (
            
                
                影片詳情頁
            
        );
    };
}

這樣,我們就實現瞭頁面的跳轉功能,但是由於Android還有物理返回鍵,因此要實現按下返回鍵時退出當前頁、在主界面 “再按一次退出程序” 的功能。

首先要攔截返回鍵事件,在主界面MainScene,添加如下代碼

import {
    ...//省略其它代碼
    BackAndroid,
    Platform,
    ToastAndroid
} from 'react-native';

export default class MainScene extends Component{
    ...//省略其它代碼
    componentDidMount(){
        this._addBackAndroidListener(this.props.navigator);
    }

    componentWillUnmount(){
        this._removeBackAndroidListener();
    }

    //監聽Android返回鍵
    _addBackAndroidListener(navigator){
        if(Platform.OS==='android'){
            var currTime = 0;
            BackAndroid.addEventListener('hardwareBackPress',()=>{
                if(!navigator){return false;}
                const routers = navigator.getCurrentRoutes();
                if(routers.length == 1){//在主界面
                    var nowTime = (new Date()).valueOf();
                    if(nowTime - currTime > 2000){
                        currTime = nowTime;
                        ToastAndroid.show("再按一次退出程序",ToastAndroid.SHORT);
                        return true;
                    }
                    return false;
                }else{//在其他子頁面
                    navigator.pop();
                    return true;
                }
            });
        }
    }
    //移除監聽
    _removeBackAndroidListener(){
        if (Platform.OS === 'android') {
            BackAndroid.removeEventListener('hardwareBackPress');
        }
    }
}

總結

至此,應用的頁面跳轉已經實現瞭,navigator對於react native 來說還是比較重要的一個組件,因為每個應用都會涉及到頁面的切換,而這都離不開對navigator的使用。看完本節的內容,應該對navigator的使用已經掌握得差不多瞭,下一節,我們將對詳情頁進行開發,其中重要的是學習如何使用原生代碼為react native提供原生能力。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *