1. 程式人生 > >breaking the habit

breaking the habit

React Native 指定頁面物理返回監聽

在Android機上,物理返回是一個很常用的功能,本文將講解如何在react-native中對物理返回進行處理,分別為主頁面連續兩次退出程式,普通頁面回到上一頁,指定頁面特殊處理。

一. 主頁面連續兩次退出程式及普通頁面返回上一頁

  1. 首先我們要先在頁面上增加物理監聽,建議在主Navigator頁面增加,就是有如下空間的頁面裡。
            <Navigator
                style={styles.navigator}
                configureScene={this.configureScene}
renderScene={this.renderScene} initialRoute=
{{ id: 'Splash', }} />
  1. 新增監聽
    componentWillMount() {
        if (Platform.OS === 'android') {
            BackAndroid.addEventListener('hardwareBackPress', this.handleBackButton);
        }
    }
    handleBackButton() {
        for
(let i = this.handlers.length - 1; i >= 0; i--) { if (this.handlers[i]()) { return true; } }//指定頁面特殊處理 const routers = this.navigator.getCurrentRoutes(); if (routers.length > 1) { this.navigator.pop(); return
true; } let now = new Date().getTime(); if (now - lastClickTime < 2500) { //2.5秒內點選後退鍵兩次推出應用程式 return false;//控制權交給原生 } lastClickTime = now; ToastAndroid.show('再按一次退出一個',ToastAndroid.SHORT); return true; }

對了 這裡的this.handleBackButton要在頁面初始化的地方bind一下

this.handleBackButton = this.handleBackButton.bind(this);
  1. 基本完成
    經過上面的處理,我們可以基本的實現對物理返回的監聽,如果不是初始頁面(即routes裡還有其他頁面),則把頁面彈出,回到上一頁,否則在2,5秒內按兩次物理返回就可以退出程式。

二. 特殊頁面的返回監聽

1. childContextTypes
    通過新增 childContextTypes 和 getChildContext() 到 context 的提    供者,React 自動向下傳遞資料然後在元件樹中的任意元件(也就是說任意子元件,在本次中將是一個函式 )都能通過定義 contextTypes 訪問 context 中的資料

大概是這麼個意思,建議要弄明白的可以自己查一下

2. 主頁面處理
     在初始化(constructor(props) )的地方建立一個數組,將用來儲存那些特定頁面的監聽函式
   this.handlers = ([]:Array<() => boolean>); 
3. 當前頁面新增兩個函式
     用來新增及刪除特殊頁面的物理監聽,並將它們提供給向下的元件樹
    addBackButtonListener(listener) {
        this.handlers.push(listener);
    }
    removeBackButtonListener(listener) {
        this.handlers = this.handlers.filter((handler) => handler !== listener);
    }

    static childContextTypes = {
        addBackButtonListener: React.PropTypes.func,
        removeBackButtonListener: React.PropTypes.func
      }
    getChildContext() {
        return {
            addBackButtonListener: this.addBackButtonListener,
            removeBackButtonListener: this.removeBackButtonListener,
        };
    }
4. 子元件(特殊頁面)特殊處理

(1) 獲取父元件的函式

  static contextTypes = {
    removeBackButtonListener: React.PropTypes.func.isRequired,
    addBackButtonListener: React.PropTypes.func.isRequired,
  };

(2) 新增新的監聽函式

    handleBackButton() {
        let {navigator} = this.props;
        let routers = navigator.getCurrentRoutes();
        if (routers[routers.length - 1].id === "XXXXXXXX") {
            //為了保險起見 因為有時候監聽不會立刻被解除安裝,防止在其他頁面觸發該監聽
            this.existAlert();//特殊處理
            return true;
        } else {
            return false;
        }
    }

(3) 將函式新增到監聽佇列中(仍要記得bind)

componentDidMount() {  
    this.context.addBackButtonListener(this.handleBackButton);              
}
componentWillUnmount() {
    this.context.removeBackButtonListener(this.handleBackButton);        
}

(4)功能完成了。

三.實現的原理

 通過childContextTypes,主頁面將增刪物理監聽的函式提供給了子頁面。在子頁面中,如果需要特殊處理物理返回監聽,可以呼叫該方法,把當前頁面的特殊處理方法新增到主頁面的監聽佇列中。當按下物理返回,會先檢視特殊監聽佇列,是否有特殊處理,有的話特殊處理,沒有的話,將按普通的物理返回進行處理

程式碼

下面是我的github上的原始碼,裡面特殊處理的頁面為滑出的抽屜
還有一些練手小東西,有興趣的可以看一下
原始碼