J'ai un Navigator
dans une application native pour Android.
J'utilise navigator.Push()
pour naviguer vers une autre page. Il semblerait naturel que le bouton Précédent ouvre le navigateur et recule d'une page, mais ce n'est pas ce qui se passe (il quitte l'application).
Navigator
n'a-t-il vraiment aucun support pour le bouton Précédent? Dois-je le connecter moi-même avec un BackAndroid
?
Oui, vous devez manipuler le bouton de retour vous-même. Je pense que la raison principale en est que vous voudrez peut-être faire différentes choses avec le bouton de retour au lieu de simplement revenir en arrière dans la pile. Cependant, je ne sais pas s'il est prévu d'intégrer la fonctionnalité du bouton arrière à l'avenir.
En plus de répondre ci-dessus, le code de traitement devrait ressembler à ceci:
var navigator;
React.BackAndroid.addEventListener('hardwareBackPress', () => {
if (navigator && navigator.getCurrentRoutes().length > 1) {
navigator.pop();
return true;
}
return false;
});
dans le code de rendu:
<Navigator ref={(nav) => { navigator = nav; }} />
Vous ne savez pas quand l'API a changé, mais à partir du moment où vous réagissez en tant que version native 0.31 (également aux versions potentiellement antérieures), BackAndroid est un composant qui doit être importé de react-native:
import {..., BackAndroid} from 'react-native'
Veillez également à supprimer le programme d'écoute sur le composantWillUnmount:
componentWillUnmount(){
BackAndroid.removeEventListener('hardwareBackPress', () => {
if (this.navigator && this.navigator.getCurrentRoutes().length > 1) {
this.navigator.pop();
return true;
}
return false;
});
}
* UPDATE: Dans la version native 0.44, ce module a été renommé en BackHandler
. Navigator
est également officiellement obsolète, mais vous pouvez toujours le trouver ici: https://github.com/facebookarchive/react-native-custom-components
import { BackHandler } from 'react-native';
N'oubliez pas bind [this]
La bonne réponse devrait être:
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}}
...
Afin de nettoyer le code en utilisant mes connaissances et mes réponses précédentes, voici à quoi il devrait ressembler:
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
}
J'ai créé un dépôt GitHub qui vous fournira un exemple de projet sur la gestion du bouton Précédent Android.
Vous pouvez cloner/télécharger le dépôt sur:
Exemple de projet de bouton de retour Android
Mais voici quelques exemples de codes sur la façon dont je gère le bouton de retour Android
Le code suivant est pour mon écran initial lorsque l'utilisateur lance mon application. En appuyant sur le bouton de retour ici affichera une alerte qui demandera à l'utilisateur s'il souhaite quitter l'application.
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>
);
}
}
Le code suivant est un écran pour lequel, lorsque l'utilisateur appuie sur le bouton Précédent, il retourne à l'écran précédent:
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>
);
}
}