处理React Native中的后退按钮,Android上的导航器

时间:2015-12-28 15:30:09

标签: android react-native

我在Android反应原生应用程序中有一个Navigator

我正在使用navigator.push()导航到其他页面。后退按钮弹出导航器并返回一页似乎很自然,但这不是正在发生的事情(退出应用程序)。

反应原生的Navigator是否真的没有后退按钮支持,我是否需要使用BackAndroid自行插入?

6 个答案:

答案 0 :(得分:49)

除了上面的回答,处理代码应该是这样的

var navigator; 

React.BackAndroid.addEventListener('hardwareBackPress', () => {
    if (navigator && navigator.getCurrentRoutes().length > 1) {
        navigator.pop();
        return true;
    }
    return false;
});

在渲染代码中:

<Navigator ref={(nav) => { navigator = nav; }} />

答案 1 :(得分:16)

不确定API何时发生变化但反应原生0.31(可能是早期版本)BackAndroid是必须从react-native导入的组件:

import {..., BackAndroid} from 'react-native'

还要确保删除componentWillUnmount上的侦听器:

componentWillUnmount(){
    BackAndroid.removeEventListener('hardwareBackPress', () => {
        if (this.navigator && this.navigator.getCurrentRoutes().length > 1) {
            this.navigator.pop();
            return true;
        }
        return false;
    });
}

*更新:在本机反应0.44中,此模块已重命名为BackHandlerNavigator也已被正式弃用,但仍可在此处找到:https://github.com/facebookarchive/react-native-custom-components

import { BackHandler } from 'react-native';

答案 2 :(得分:7)

是的,您必须自己处理后退按钮。我认为这样做的主要原因是您可能希望使用后退按钮执行不同的操作,而不是仅仅通过堆栈向后移动。我不知道是否有计划在未来采用后退按钮功能。

答案 3 :(得分:6)

不要忘记bind [this]

正确的答案应该是:

export default class MyPage extends Component {
  constructor(props) {
    super(props)
    this.navigator = null;

    this.handleBack = (() => {
      if (this.navigator && this.navigator.getCurrentRoutes().length > 1){
        this.navigator.pop();
        return true; //avoid closing the app
      }

      return false; //close the app
    }).bind(this) //don't forget bind this, you will remember anyway.
  }

  componentDidMount() {
    BackAndroid.addEventListener('hardwareBackPress', this.handleBack);
  }

  componentWillUnmount() {
    BackAndroid.removeEventListener('hardwareBackPress', this.handleBack);
  }

  render() {
    return (
      <Navigator
        ref={navigator => {this.navigator = navigator}}
  ...

答案 4 :(得分:1)

为了使用我的知识和以前的答案清理代码,下面是它的样子:

import { ..., Navigator, BackAndroid } from 'react-native';

componentDidMount() {
  BackAndroid.addEventListener('hardwareBackPress', this.handleBack);
}

componentWillUnmount() {
  //Forgetting to remove the listener will cause pop executes multiple times
  BackAndroid.removeEventListener('hardwareBackPress', this.handleBack);
}

handleBack() {
  if (this.navigator && this.navigator.getCurrentRoutes().length > 1){
    this.navigator.pop();
    return true; //avoid closing the app
  }

  return false; //close the app
}

答案 5 :(得分:1)

我创建了一个GitHub存储库,它将为您提供有关如何处理Android Back Button的示例项目。

您可以在以下位置克隆/下载存储库:

Android Back Button Sample Project

但这是一些有关如何处理android后退按钮的示例代码

以下代码用于用户启动我的应用程序时的初始屏幕。按此处的“后退”按钮将显示一个警报,询问用户是否要离开该应用程序。

import React, {Component} from 'react';
import {View,Text,Button,BackHandler,Alert} from 'react-native';
import {NavigationActions} from 'react-navigation';

export default class InitScreen extends Component {
    _focusDoneSubscribe;//declaring variable that will be listener for the back button when in focus 
    _blurGoingSubscribe;//declaring variable that will be listener for the back button when blur 

    //the following will remove the navigation bar at the top
    static navigationOptions = {
        header: null,
        title: 'Welcome',
    };

    constructor(props)
    {
        super(props);
        this._focusDoneSubscribe = props.navigation.addListener('didFocus', payload =>
            BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
        );//this assigns the listener
    }
    //functions to handle back button events
    componentDidMount()
    {
        this._blurGoingSubscribe = this.props.navigation.addListener('willBlur', payload =>
                BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
            );
    }

    onBackButtonPressAndroid = () => {
        Alert.alert(
            'Exiting App',
            'Confirm quitting the app?',
            [
                {text: 'CANCEL', style: 'cancel'},
                {text: 'STOP ASKING AND QUIT', onPress: () => BackHandler.exitApp()}
            ],
            {cancelable: false},
        );
        return true;
    };

    componentWillUnmount()
    {
        this._focusDoneSubscribe && this._focusDoneSubscribe.remove();
        this._blurGoingSubscribe && this._blurGoingSubscribe.remove();
    }
    //actual render
    render(){
        const { navigate } = this.props.navigation;
        return (
            <View style={{alignItems: 'center'}}>
                <View style={{height: 100,justifyContent: 'center',alignItems: 'center'}}>
                    <Text style={{fontSize: 20}}>Navigation BackHandler Tutorial</Text>
                    <Text style={{fontSize: 20}}>Initial Screen</Text>
                </View>
                <View style={{flexDirection: 'column', justifyContent: 'space-between', height: 100}}>
                    <Button
                    title="SCREEN ONE"
                    onPress={() => {this.props.navigation.push('One')}}
                    />
                    <Button
                    title="SCREEN TWO"
                    onPress={() => {this.props.navigation.push('Two')}}
                    />
                </View>
            </View>
        );
    }
}

以下代码是一个屏幕,当用户按下后退按钮时,它将返回上一屏幕:

import React, {Component} from 'react';
import {View,Text,Button,BackHandler} from 'react-native';//declaring variable that will be listener for the back button when in focus 
import {NavigationActions} from 'react-navigation';//declaring variable that will be listener for the back button when blur 

export default class ScreenOne extends Component {
    _focusDoneSubscribe;
    _blurGoingSubscribe;

    //the following will remove the navigation bar at the top
    static navigationOptions = {
        header: null,
        title: 'ONE',
    };

    constructor(props)
    {
        super(props);
        this._focusDoneSubscribe = props.navigation.addListener('didFocus', payload =>
            BackHandler.addEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
        );//this assigns the listener
    }
    //functions to handle back button events
    componentDidMount()
    {
        this._blurGoingSubscribe = this.props.navigation.addListener('willBlur', payload =>
                BackHandler.removeEventListener('hardwareBackPress', this.onBackButtonPressAndroid)
            );
    }

    onBackButtonPressAndroid = () => {
        this.props.navigation.goBack();
        return true;
    };

    componentWillUnmount()
    {
        this._focusDoneSubscribe && this._focusDoneSubscribe.remove();
        this._blurGoingSubscribe && this._blurGoingSubscribe.remove();
    }
    //actual render
    render(){
        const { navigate } = this.props.navigation;
        return (
            <View style={{alignItems: 'center'}}>
                <View style={{height: 100,justifyContent: 'center',alignItems: 'center'}}>
                    <Text style={{fontSize: 20}}>Navigation BackHandler Tutorial</Text>
                    <Text style={{fontSize: 20}}>SCREEN ONE</Text>
                </View>
            </View>
        );
    }
}