如何阻止 Android 硬件后退按钮在 react-native 的 react-navigation 中运行?

How to stop the Android Hardware Back Button from functioning in react-navigation for react-native?

我正在开发一个问答游戏,我正在使用 react-navigation 来处理导航,我有 3 个组件,(newGame、Questions、Results)我不希望用户返回结果中的问题页如果没有。问题已经用完,但是,按下后退按钮( Android 硬件 )将他带回问题。然后我尝试像这样处理硬件后退按钮:

componentWillMount() {
      this.props.gameState(true);
      BackHandler.addEventListener('hardwareBackPress', () => {
        if (this.props.gamePlaying) { // Currently set to true. I will set it to false again on NewGame Page.
          this.props.navigation.navigate('NewGame');
        }
      });
    }

但是,这会将用户带到 NewGame 屏幕,但会立即弹回结果页面,因为它会立即在 NewGame 页面中触发 NAVIGATION/BACK。这再次将其带回结果页面。

可能的修复方法?

我想在进入 NewGame 组件页面后停止触发后退按钮。有办法吗?

我的环境

反应导航=^1.0.0-beta.11 本机反应 = 0.44.0

您需要 return true 来表明您已经自己处理了后退按钮,正如您在 docs.

中看到的那样

if one subscription returns true then subscriptions registered earlier will not be called

您的代码应如下所示:

componentWillMount() {
    this.props.gameState(true);
    BackHandler.addEventListener('hardwareBackPress', () => {
        if (this.props.gamePlaying) {
            this.props.navigation.navigate('NewGame');
            return true; // This will prevent the regular handling of the back button
        }

        return false;
    });
}

停止按钮运行的一种方法是在启动时将逻辑引入 BackHandler 事件监听器,如下所示:

BackHandler.addEventListener('hardwareBackPress', () => {
    const { dispatch, nav } = this.props
    if (nav.routes.length === 1 && (nav.routes[0].routeName === 'Login' || nav.routes[0].routeName === 'Start')) return false
    dispatch({ type: 'Navigation/BACK' })
    return true
})

注意我们是如何观察情况的。这道题的关键是来自事件监听器的returntruefalsefalse 停止硬件后退按钮的功能。 true clean-exits from the event.

这里再举一个例子来说明:

BackHandler.addEventListener('hardwareBackPress', () => {
    const { dispatch, nav } = this.props
    if (nav.routes[0].routeName === 'TriviaQuestion') return false
    if (!playTimeLeft && (nav.routes[0].routeName === 'TriviaQuestion')) return false
    if (nav.routes[0].routeName === 'InvasiveDialog') return false
    dispatch({ type: 'Navigation/BACK' })
    return true
})

下面是一些示例代码,除了让“后退”按钮停止运行之外,还有更多用途可供查看:

import React, { Component } from 'react'
import { Platform, BackHandler } from 'react-native'
import { Provider, connect } from 'react-redux'
import { addNavigationHelpers } from 'react-navigation'
import { NavigationStack } from './navigation/nav_reducer'
import store from './store'

class App extends Component {
    componentWillMount() {
        if (Platform.OS !== 'android') return
        BackHandler.addEventListener('hardwareBackPress', () => {
            const { dispatch, nav } = this.props
            if (nav.routes.length === 1 && (nav.routes[0].routeName === 'Login' || nav.routes[0].routeName === 'Start')) return false
            dispatch({ type: 'Navigation/BACK' })
            return true
        })
    }

    componentWillUnmount() {
        if (Platform.OS === 'android') BackHandler.removeEventListener('hardwareBackPress')
    }

    render() {
        const { dispatch, nav } = this.props
        const navigation = addNavigationHelpers({
            dispatch,
            state: nav
        })
        return <NavigationStack navigation={navigation} />
    }
}

const mapStateToProps = ({ nav }) => ({ nav })
const RootNavigationStack = connect(mapStateToProps)(App)

const Root = () => (
    <Provider store={store}>
        <RootNavigationStack />
    </Provider>
)

export default Root

如果您在尝试使后退按钮正常工作时发现此 post,请尽可能接近地复制我的上一个示例。完全按照所示使用事件侦听器并首先测试您的应用程序以了解其工作原理。

If you are using Redux, this is what you want.

NavigationStack 只是引用另一个文件中的 export const NavigationStack = StackNavigator({ ...etc })

当用户在 StackNavigator 中切换屏幕时默认有一个后退按钮,我们可以通过将 headerLeft 设置为 null 来修复它

static navigationOptions =({navigation}) => {
    return {
        title: 'Rechercher une ville',
        headerLeft: null,
    }  
}