禁用后退按钮,但是当点击两次退出应用程序时反应原生

Posted

技术标签:

【中文标题】禁用后退按钮,但是当点击两次退出应用程序时反应原生【英文标题】:Disable back button but when tap twice exit app in react native 【发布时间】:2021-07-12 01:55:07 【问题描述】:

我正在尝试创建一个小型反应原生应用程序,并且在该应用程序中,我创建了一些屏幕。在特定屏幕上,我想禁用系统后退按钮,我这样做了,但我想在同一个屏幕上创建一个逻辑,如果用户点击两次,那么应用程序将被关闭。

我的屏幕

import React, Component, useEffect from 'react';
import StyleSheet, Text, View, Button, BackHandler, Alert from 'react-native';

export default function HomeScreen(navigation) 
  useEffect(() => 
    BackHandler.addEventListener('hardwareBackPress', () => true);
    return () =>
      BackHandler.removeEventListener('hardwareBackPress', () => true);
  , []);

  return (
    <View style=flex: 1, alignItems: 'center', justifyContent: 'center'>
      <Text>Home Screen</Text>
      <Button
        title="Go to Other Screen"
        onPress=() => navigation.navigate('Employees')
      />
    </View>
  );

但还有一个问题,此代码禁用每个屏幕上的后退按钮。

【问题讨论】:

【参考方案1】:

对于按下硬件按钮两次退出部分,您可以创建一些状态,增加它,当它等于 2 时使用 Backhandler's exitApp function 退出应用程序。

如果您只希望Backhandler 事件代码对HomeScreen 组件有效,您可以使用useFocusEffect

React Navigation 提供了一个钩子,当屏幕聚焦时运行效果并在失焦时清理它

Source

function HomeScreen(navigation) 
  const [backPressedCount, setBackPressedCount] = useState(0);

  useFocusEffect(
    useCallback(() => 
      BackHandler.addEventListener('hardwareBackPress', () => 
        setBackPressedCount((backPressedCount) => backPressedCount + 1);
        return true;
      );
      return () =>
        BackHandler.removeEventListener('hardwareBackPress', () => true);
    , []),
  );

  useEffect(() => 
    if (backPressedCount === 2) 
      BackHandler.exitApp();
    
  , [backPressedCount]);

  return (
    <View style=flex: 1, alignItems: 'center', justifyContent: 'center'>
      <Text>Home Screen</Text>
      <Button
        title="Go to Other Screen"
        onPress=() => navigation.navigate('Employees')
      />
    </View>
  );

【讨论】:

【参考方案2】:

基于接受的答案 (Bas van der Linden)。我创建了这个有用的钩子:

钩子

const usePreventCloseApp = (onBeforeCloseApp) => 
    const [backPressedCount, setBackPressedCount] = useState(0);

    useFocusEffect(
        useCallback(() => 
            const sub = BackHandler.addEventListener(
                'hardwareBackPress',
                () => 
                    if (onBeforeCloseApp) 
                        onBeforeCloseApp(() => setBackPressedCount(2));
                     else 
                        setBackPressedCount((pre) => 
                            if (pre === 0) 
                                Toastandroid.show('Press again to exit', 1000);
                                setTimeout(() => setBackPressedCount(0), 1000);
                            
                            return pre + 1;
                        );
                    
                    return true;
                ,
            );
            return sub.remove;
        , [onBeforeCloseApp]),
    );

    useEffect(() => 
        if (backPressedCount === 2) 
            BackHandler.exitApp();
        
    , [backPressedCount]);

    return 
        closeApp: () => setBackPressedCount(2),
    ;
;

用法

显示默认吐司“再次按下退出”

const  closeApp  = usePreventCloseApp();

带有自定义回调

usePreventCloseApp((closeApp) => 
     Alert.alert('Close App', 'Are you sure want to close app?', [
         
             text: 'Cancel',
             style: 'cancel',
         ,
         
             text: 'Close App',
             style: 'destructive',
             onPress: closeApp,
         ,
     ]);
 );

【讨论】:

以上是关于禁用后退按钮,但是当点击两次退出应用程序时反应原生的主要内容,如果未能解决你的问题,请参考以下文章

单击两次后退按钮以退出活动

在反应导航中禁用后退按钮

当标签栏点击两次时禁用自动弹出到根视图控制器

如何在主页中打开后退按钮 android 以退出应用程序并关闭反应本机导航侧菜单

注销后的 CodeIgniter 后退按钮

在jsp中注销时禁用后退按钮[重复]