React Native StackNavigator Android 物理返回按钮处理

这篇博客详细介绍了如何处理React Native的StackNavigator在Android设备上的物理返回按钮问题,特别是针对release包下直接退出应用的异常情况。通过引入BackHandler和自定义全局数据存储,解决了监听返回键并实现按两次退出应用的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

React Native StackNavigator Android 物理返回按钮处理(这里只做按两次退出应用的处理)
一、首先引入BackHandler
import { StackNavigator } from ‘react-navigation’;//引入StackNavigator
import { BackHandler,ToastAndroid ,View} from ‘react-native’;//由于这儿用到了Toast提示,便一起引入

    首先列出项目入库文件App.js代码:
    import {BackHandler, ToastAndroid ,View ,Platform} from 'react-native';
    import {StackNavigator} from 'react-navigation';
    import HomeScreen from './js/screen/HomeScreen';
    import MineScreen from "./js/screen/MineScreen";
    var stateIndex, oStateIndex = false, goBack = false;
    var lastBackPressed;
    var current = true;

    type Props = {};
    type State = {};
    export default class App extends PureComponent<Props, State> {
        componentWillUnmount() {//注册返回按钮事件监听
            this.backHandler && this.backHandler.remove();
        }

        componentDidMount() {//移除返回按钮事件监听
            this.backHandler = BackHandler.addEventListener('hardwareBackPress',
            this.backOption);
        }

        backOption = () => {
            if (current == true) {//如果是在首页
                if (lastBackPressed && lastBackPressed + 2000 >= Date.now()) {
                    //最近2秒内按过back键,可以退出应用。
                    BackHandler.exitApp();
                    return false;
                }

                lastBackPressed = Date.now();
                ToastAndroid.show('再按一次退出应用', ToastAndroid.SHORT);
                return true;
             } else {
                if (this.props && this.props.navigation) {
                this.props.navigator.pop();
             }
            }
       }

        render() {
            return (
                <View style={flex:1}
                 <Navigator
                        onNavigationStateChange={(prevState, newState, action) => {//注册路由改变监听事件
                            if (newState && newState.routes[newState.routes.length - 1].routeName == 'HomeScreen') {//如果当前路由是Home页面,则需要处理安卓物理返回按键。
                                current = true;
                            } else {
                                current = false;
                            }
                    }}                 
                ></Navigator>
            </View>
        );
    }
}

    const Navigator = StackNavigator(
    {
        HomeScreen: {screen: HomeScreen},
        MineScreen: {screen: MineScreen},
    },
    {
        initialRouteName: 'HomeScreen',
        navigationOptions: {
            header: null,
            gesturesEnabled: Platform.OS == 'ios' ? true : false,
            headerTintColor: '#333333',
            headerBackTitle: null
        },
    }
)

二、自己根据需求编写Home.js和MineScreen.js文件,这里就不列出代码了。
附录:如果有的童鞋是用的Navigator导航,可以使用如下方式:

    componentWillMount() {
        BackHandler.addEventListener('hardwareBackPress', this.onBackAndroid);
    }

    componentWillUnmount() {
        BackHandler.removeEventListener('hardwareBackPress', this.onBackAndroid);
    }
    onBackAndroid = () => {
        const nav = this.props.navigator;
        const routers = nav.getCurrentRoutes();
        if (routers.length > 1) {
          nav.pop();
          return true;
        }else {
            if (lastBackPressed && lastBackPressed + 2000 >= Date.now()) {
                   return false;
               }
               lastBackPressed = Date.now();
               ToastAndroid.show('再按一次退出应用',1000);
               return true;
            }
    };

留言:本篇博客主要记录自己在第一次处理安卓返回按钮监听和处理上的一些方式和技巧。
**附言:有的Android同鞋存在确实添加了BackHandler监听,在debug apk包下也能正常监听安卓手机的返回按钮,页面能够正常返回。

但是:在release包下按安卓物理返回键却会直接退出app。

针对这种情况,我还没找到更好的解决方法,这里只贴出我个人的处理办法:
第一步:创建一个全局的数据存储类。

DataObject.js
代码如下:
const object = {
    //用来保存App.js所在类对象
    APP:{},

};
export default object;

第二步:在App.js的构造方法中为DataObject类中的App变量赋值。
第三步:在/node_modules/react-native/Libraries/Utilities/BackHandler.android.js
文件中找到该处代码:
首先引入我们定义的DataObject类

    import DataObject from '../../../../js/localData/DataObject'//引入我们定义的DataObject类
    RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function () {
    let invokeDefault = true;
    const subscriptions = Array.from(_backPressSubscriptions.values()).reverse();
    for (let i = 0; i < subscriptions.length; ++i) {
        if (subscriptions[i]()) {
            invokeDefault = false;
            break;
        }
    }

    if (invokeDefault) {
        //此处删除系统原有代码,添加如下代码
        //TODO
        if(DataObject.APP != undefined && DataObject.APP.backOption != undefined){//判断如果DataObject.APP未定义则不执行。
                DataObject.APP.backOption()//调用APP.js中我们的backOption方法。
            }
        }
    });

App.js类所有代码:

import DataObject from './js/localData/DataObject';
import {BackHandler, ToastAndroid ,View ,Platform} from 'react-native';
import {StackNavigator} from 'react-navigation';
import HomeScreen from './js/screen/HomeScreen';
import MineScreen from "./js/screen/MineScreen";
var stateIndex, oStateIndex = false, goBack = false;
var lastBackPressed;
var current = true;

type Props = {};
type State = {};
export default class App extends PureComponent<Props, State> {
    //构造方法
    constructor(props){
        super(props)
        DataObject.APP = this //为DataObject类中的App变量赋值
    }
    backOption = () => {
        if (current == true) {//如果是在首页
            if (lastBackPressed && lastBackPressed + 2000 >= Date.now()) {
                //最近2秒内按过back键,可以退出应用。
                BackHandler.exitApp();
                return false;
            }

            lastBackPressed = Date.now();
            ToastAndroid.show('再按一次退出应用', ToastAndroid.SHORT);
            return true;
         } else {
            if (this.props && this.props.navigation) {
            this.props.navigator.pop();
         }
        }
   }

    render() {
        return (
            <View style={flex:1}
             <Navigator
                    onNavigationStateChange={(prevState, newState, action) => {//注册路由改变监听事件
                        if (newState && newState.routes[newState.routes.length - 1].routeName == 'HomeScreen') {//如果当前路由是Home页面,则需要处理安卓物理返回按键。
                            current = true;
                        } else {
                            current = false;
                        }
                }}                 
            ></Navigator>
        </View>
    );
}
const Navigator = StackNavigator(
{
    HomeScreen: {screen: HomeScreen},
    MineScreen: {screen: MineScreen},
},
{
    initialRouteName: 'HomeScreen',
    navigationOptions: {
        header: null,
        gesturesEnabled: Platform.OS == 'ios' ? true : false,
        headerTintColor: '#333333',
        headerBackTitle: null
    },
}

)
**

到此为止,解决完Android物理返回键在使用StackNavigator导航器时存在的问题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值