后退按钮反应本机退出应用程序

时间:2017-09-21 10:10:10

标签: react-native react-native-android

我已将android后退按钮退出我的主屏幕中的本机应用中的应用功能。但是当我在其他屏幕上按下android后退按钮时,它也会被调用。

componentDidMount() {

    if (Platform.OS == "android") {
        BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);                           
  }
    this._setupGoogleSignin();           
    this._getUserDetails();
    const { navigate } = this.props.navigation;
    console.log("object url is", this.state.postsArray[0].url);

}

handleBackButton = () => {               
    Alert.alert(
        'Exit App',
        'Exiting the application?', [{
            text: 'Cancel',
            onPress: () => console.log('Cancel Pressed'),
            style: 'cancel'
        }, {
            text: 'OK',
            onPress: () => BackHandler.exitApp()
        }, ], {
            cancelable: false
        }
     )
     return true;
   }
componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
  }

9 个答案:

答案 0 :(得分:15)

如果您在导航到其他屏幕时仍然安装了HomeScreen,或者在卸载HomeScreen时如果您没有删除EventListener,则仍然会调用它。

您应该在导航或卸载时清除EventListener,

onButtonPress = () => {
  BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
  // then navigate
  navigate('NewScreen');
}

handleBackButton = () => {
 Alert.alert(
     'Exit App',
     'Exiting the application?', [{
         text: 'Cancel',
         onPress: () = > console.log('Cancel Pressed'),
         style: 'cancel'
     }, {
         text: 'OK',
         onPress: () = > BackHandler.exitApp()
     }, ], {
         cancelable: false
     }
  )
  return true;
} 

componentDidMount() {
  BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}

componentWillUnmount() {
  BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}

答案 1 :(得分:4)

如果您不希望“警报”消息出现在其他组件/屏幕中,而只出现在一个特定的组件/屏幕中,则可以执行此操作。

import { withNavigationFocus } from 'react-navigation';

class TestComponent extends Component {
  componentWillMount() {
    BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
  }

  handleBackButton = () => {
    if (this.props.isFocused) {
      Alert.alert(
        'Exit App',
        'Exiting the application?',
        [
          {
            text: 'Cancel',
            onPress: () => console.log('Cancel Pressed'),
            style: 'cancel'
          },
          {
            text: 'OK',
            onPress: () => BackHandler.exitApp()
          }
        ],
        {
          cancelable: false
        }
      );
      return true;
    }
  };
} 

export default withNavigationFocus(TestComponent );

将显示警报消息的BackHandler仅在TestComponent中工作

答案 2 :(得分:3)

我们可以在主应用容器中添加 didfocus 订阅 。我们可以添加逻辑来检查点击带有 静态变量 的按钮。

import {  Alert,  BackHandler,  ToastAndroid } from 'react-native';
import {  StackActions } from 'react-navigation';
import { Toast } from 'native-base';
// common statless class variable.
let backHandlerClickCount = 0;

class App extends React.Component {
    constructor(props) {
      super(props);
      // add listener to didFocus
      this._didFocusSubscription = props.navigation.addListener('didFocus', payload =>
        BackHandler.addEventListener('hardwareBackPress', () => this.onBackButtonPressAndroid(payload)));
    }

    // remove listener on unmount 
    componentWillUnmount() {
      if (this._didFocusSubscription) {
        this._didFocusSubscription.remove();
      }
    }

    onBackButtonPressAndroid = () => {
      const shortToast = message => {
        // ToastAndroid.showWithGravityAndOffset(
        //     message,
        //     ToastAndroid.SHORT,
        //     ToastAndroid.BOTTOM,
        //     25,
        //     50
        // );

        // ios & android
        Toast.show({
            text: message,
            type: 'warning',
            position: 'top',
            duration: 3000,
        });
        }

        const {
          clickedPosition
        } = this.state;
        backHandlerClickCount += 1;
        if ((clickedPosition !== 1)) {
          if ((backHandlerClickCount < 2)) {
            shortToast('Press again to quit the application!');
          } else {
            BackHandler.exitApp();
          }
        }

        // timeout for fade and exit
        setTimeout(() => {
          backHandlerClickCount = 0;
        }, 2000);

        if (((clickedPosition === 1) &&
            (this.props.navigation.isFocused()))) {
          Alert.alert(
            'Exit Application',
            'Do you want to quit application?', [{
              text: 'Cancel',
              onPress: () => console.log('Cancel Pressed'),
              style: 'cancel'
            }, {
              text: 'OK',
              onPress: () => BackHandler.exitApp()
            }], {
              cancelable: false
            }
          );
        } else {
          this.props.navigation.dispatch(StackActions.pop({
            n: 1
          }));
        }
        return true;
      }

    }

答案 3 :(得分:2)

Guyz请务必理解,这可能不仅是react native问题。将其与Firebase集成时请小心。最新的firebase版本存在在本机应用程序中集成后退按钮的问题!!请将Firebase版本降级为firebase-version @ 5.0.3,然后重新检查其是否有效!我有同样的问题,担心了好几天。我终于降级到@ 5.0.3版本,现在后退按钮可以正常使用!如果仍然遇到问题,您可以降级到较低的版本。

答案 4 :(得分:2)

只需添加其他答案

如果您使用的是'@react-navigation/native',则即使您已导航到子屏幕,也可以在backButton上设置eventListner。要克服在focus而非componentDidMount()上设置的eventListner的问题,并在屏幕上发生blur事件时将其删除。

Learn more about react-navigation events here

export class sampleScreen extends Component {
constructor(props) {
    super(props);
    this.state = {
        foo: '',
        bar: '',
    };

    this._unsubscribeSiFocus = this.props.navigation.addListener('focus', e => {
        console.warn('focus signIn');
        BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
    });
    this._unsubscribeSiBlur = this.props.navigation.addListener('blur', e => {
        console.warn('blur signIn');
        BackHandler.removeEventListener(
            'hardwareBackPress',
            this.handleBackButton,
        );
    });

    onButtonPress = () => {
        BackHandler.removeEventListener(
            'hardwareBackPress',
            this.handleBackButton,
        );
    };
}

handleBackButton = () => {
    Alert.alert(
        'Exit App',
        'Exiting the application?',
        [{
                text: 'Cancel',
                onPress: () => console.log('Cancel Pressed'),
                style: 'cancel',
            },
            {
                text: 'OK',
                onPress: () => BackHandler.exitApp(),
            },
        ], {
            cancelable: false,
        },
    );
    return true;
};

componentDidMount() {
    // BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}

componentWillUnmount() {
    this._unsubscribeSiFocus();
    this._unsubscribeSiBlur();
    BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}

}

答案 5 :(得分:0)

BackHandler.addEventListener('hardwareBackPress', function() {
    Alert.alert(
      'Thoát Khỏi Ứng Dụng',
      'Bạn có muốn thoát không?', [{
          text: 'Cancel',
          onPress: () => console.log('Cancel Pressed'),
          style: 'cancel'
      }, {
          text: 'OK',
          onPress: () => BackHandler.exitApp()
      }, ], {
          cancelable: false
      }
   )
   return true;
})

答案 6 :(得分:0)

您始终可以根据当前场景动态修改BackHandler.addEventListener的回调函数(使用react-native-router-flux可以很容易地做到这一点)。

import { Actions } from 'react-native-router-flux'

handleBackPress = () => {
 switch (Actions.currentScene) {
   case 'home':
     BackHandler.exitApp()
     break

   default: Actions.pop()
 }

 return true
}

完整的要旨可以在这里找到:https://gist.github.com/omeileo/f05a068557e9f0a2d8a24ecccd2f3177

答案 7 :(得分:0)

如果您想回退,请按退出应用程序

import React, {useEffect} from 'react';
import {BackHandler} from 'react-native';
import {Provider} from 'react-redux';
import Toast from 'react-native-root-toast';

let backHandlerClickCount = 0;

const App = () => {
    useEffect(() => {
        // back handle exit app
        BackHandler.addEventListener('hardwareBackPress', backButtonHandler);
        return () => {
            BackHandler.removeEventListener('hardwareBackPress', backButtonHandler);
        };
    }, []);
    const backButtonHandler = () => {
        const shortToast = message => {
            Toast.show(message, {
                duration: Toast.durations.LONG,
                position: Toast.positions.BOTTOM,
            });
        }

        backHandlerClickCount += 1;
        if ((backHandlerClickCount < 2)) {
            shortToast('Press again to quit the application');
        } else {
            BackHandler.exitApp();
        }

        // timeout for fade and exit
        setTimeout(() => {
            backHandlerClickCount = 0;
        }, 1000);

        return true;
    }
    return (
        <Provider store={store}>
         ....
        </Provider>
    );
};

export default App;

答案 8 :(得分:0)

我在这个问题上也有问题,但是我设法以非常简单的方式解决了它。我正在使用反应导航4.4.1。

.uppercase()