240 votes

Comment désactiver ou remplacer le bouton "RETOUR" d'Android dans Flutter?

Y a-t-il un moyen de désactiver le bouton retour d'Android sur une page spécifique ?

class WakeUpApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "Time To Wake Up ?",
      home: new WakeUpHome(),
      routes: {
        '/pageOne': (BuildContext context) => new pageOne(),
        '/pageTwo': (BuildContext context) => new pageTwo(),
      },
    );
  }
}

Sur la pageOne, j'ai un bouton pour aller à la pageTwo :

new FloatingActionButton(
  onPressed: () {    
    Navigator.of(context).pushNamed('/pageTwo');
  },
)

Mon problème est que si je presse la flèche de retour en bas de l'écran Android, je retourne à la pageOne. Je voudrais que ce bouton ne s'affiche pas du tout. Idéalement, je voudrais qu'il n'y ait aucun moyen de sortir de cet écran sauf si l'utilisateur garde par exemple son doigt appuyé sur l'écran pendant 5 secondes. (Je suis en train d'écrire une application pour les tout-petits, et je voudrais que seuls les parents puissent naviguer hors de l'écran en question).

435voto

Rémi Rousselet Points 45139

La réponse est WillPopScope. Cela empêchera la page d'être supprimée par le système. Vous pourrez toujours utiliser Navigator.of(context).pop()

@override
Widget build(BuildContext context) {
  return new WillPopScope(
    onWillPop: () async => false,
    child: new Scaffold(
      appBar: new AppBar(
        title: new Text("data"),
        leading: new IconButton(
          icon: new Icon(Icons.ac_unit),
          onPressed: () => Navigator.of(context).pop(),
        ),
      ),
    ),
  );
}

6 votes

Pour ceux qui veulent intercepter l'apparition d'un formulaire, il est plus pratique d'utiliser la propriété onWillPop du formulaire. Elle a accès à l'état du formulaire et peut d'abord vérifier s'il y a un état que l'utilisateur ne veut pas perdre.

0 votes

Bonjour @RémiRousselet , Pouvez-vous s'il vous plaît m'aider à gérer la pile arrière comme j'ai une pile d'écrans A, B, C, D et je veux naviguer de D->B OU D->A , comment puis-je gérer cela. Pouvez-vous s'il vous plaît me guider à ce sujet

1 votes

Je sais que cette réponse est peut-être ancienne. Mais c'est une PERLE! Pensez à agrandir l'explication. Ça fonctionne super bien. Merci.

56voto

marcg Points 110

Comme l'a souligné Rémi Rousselet, WillPopScope est généralement la solution à adopter. Cependant, si vous développez un widget à état qui doit réagir directement au bouton de retour, vous pouvez utiliser ceci :

https://pub.dartlang.org/packages/back_button_interceptor

Note : Je suis l'auteur de ce package.

0 votes

Avec tout le respect dû, ne pensez-vous pas que cela conviendrait mieux en tant que commentaire?

49 votes

@CopsOnRoad Non, car ce n'est pas un commentaire à une autre réponse, mais plutôt une manière totalement différente de résoudre le même problème.

8 votes

C'est une bonne alternative et cela aurait pu être ignoré s'il faisait partie d'un commentaire.

19voto

CopsOnRoad Points 4705

Vous pouvez utiliser Future.value(bool) pour gérer le bouton retour.

bool _allow = true;

@override
Widget build(BuildContext context) {
  return WillPopScope(
    child: Scaffold(appBar: AppBar(title: Text("Retour"))),
    onWillPop: () {
      return Future.value(_allow); // si vrai, autoriser le retour, sinon le bloquer
    },
  );
}

2 votes

FYI, ceci est équivalent à onWillPop: () async => _allow.

0 votes

@Lynn oui je sais. Je voulais juste partager l'appel Future.value().

0 votes

@LesFlicsDansLaRue retourne SafeArea() déjà défini alors comment gérer le retour en arrière dans un flutter

7voto

Bryan Cancel Points 64

Je poste ceci ici au cas où quelqu'un le trouve et souhaite trouver un exemple simple https://gist.github.com/b-cancel/0ca372017a25f0c120b14dfca3591aa5

import 'package:flutter/material.dart';

import 'dart:async';

void main() => runApp(new BackButtonOverrideDemoWidget());

class BackButtonOverrideDemoWidget extends StatefulWidget{
  @override
  _BackButtonOverrideDemoWidgetState createState() => new _BackButtonOverrideDemoWidgetState();
}

class _BackButtonOverrideDemoWidgetState extends State with WidgetsBindingObserver{

  //-------------------------Variable de test

  bool isBackButtonActivated = false;

  //-------------------------Nécessaire pour WidgetsBindingObserver

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  //-------------------------Fonction qui se déclenche lorsque vous appuyez sur la touche de retour

  @override
  didPopRoute(){
    bool override;
    if(isBackButtonActivated)
      override = false;
    else
      override = true;
    return new Future.value(override);
  }

  //-------------------------Méthode de construction

  @override
  Widget build(BuildContext context) {
    return new Directionality(
      textDirection: TextDirection.ltr,
      child: new Container(
          color: (isBackButtonActivated) ? Colors.green : Colors.red,
          child: new Center(
              child: new FlatButton(
                color: Colors.white,
                onPressed: () {
                  isBackButtonActivated = !isBackButtonActivated;
                  setState(() {});
                },
                child: (isBackButtonActivated) ?
                new Text("Désactiver le bouton retour") : new Text("Activer le bouton retour"),
              )
          )
      ),
    );
  }
}

0 votes

J'ai littéralement utilisé moi-même hier. Gardez à l'esprit que c'est uniquement pour Android, Apple n'a pas de bouton de retour. Bien que pourriez-vous peut-être me dire ce qui ne va pas pour que je puisse le réparer, ou peut-être cela fonctionne-t-il uniquement sur mon émulateur particulier. Je n'ai pas mis à jour mon flutter depuis quelques semaines alors peut-être que c'est le problème. Faites-moi savoir

1 votes

@BryanCancel Votre réponse fonctionne seulement si vous n'avez pas encore de routes poussées. Voir la méthode WidgetsBinding.handlePopRoute(). Il notifie les observateurs dans l'ordre d'inscription, et s'arrête dès qu'il reçoit true. Lorsqu'il y a des routes poussées, le navigateur renvoie true en premier, et puis votre observateur n'est en réalité jamais appelé. En d'autres termes, votre code fonctionne seulement pour empêcher l'application de se fermer lorsque l'utilisateur clique sur le bouton retour, s'il ne reste plus de routes.

0voto

icazevedo Points 50

Vous devriez utiliser la méthode popAndPushNamed au lieu de pushNamed. Elle fait sortir la route actuelle et pousse la route souhaitée.

Ceci étant dit, votre code FAB devrait ressembler à ceci

new FloatingActionButton(
  onPressed: () {    
    Navigator.popAndPushNamed(context, '/pageTwo');
  },
)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X