Czy istnieje sposób na dezaktywację przycisku Wstecz Androida na określonej stronie?
class WakeUpApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: "Time To Wake Up ?",
home: new WakeUpHome(),
routes: <String, WidgetBuilder>{
'/pageOne': (BuildContext context) => new pageOne(),
'/pageTwo': (BuildContext context) => new pageTwo(),
},
);
}
}
Na pageOne Mam przycisk, aby przejść do strony Dwa:
new FloatingActionButton(
onPressed: () {
Navigator.of(context).pushNamed('/pageTwo');
},
)
Mój problem polega na tym, że jeśli naciśnę strzałkę Wstecz u dołu ekranu Androida, wracam do strony pierwszej. Chciałbym, żeby ten przycisk w ogóle się nie pojawiał. Najlepiej, gdybym nie miał możliwości wyjścia z tego ekranu, chyba że użytkownik przykładowo przytrzyma palec na ekranie przez 5 sekund. (Próbuję napisać aplikację dla małych dzieci i chciałbym, aby tylko rodzice mogli opuścić dany ekran).
onWillPop
. Ma dostęp do stanu formularza i może najpierw sprawdzić, czy istnieje stan, którego użytkownik nie chciałby utracić.onWillPop: () async { onBack(); // "DO YOUR FUNCTION IS HERE WHEN POP" return false; }
Jak zauważył Rémi Rousselet,
WillPopScope
zazwyczaj jest to najlepszy sposób. Jeśli jednak tworzysz widżet stanowy, który powinien reagować bezpośrednio na przycisk Wstecz, możesz użyć tego:https://pub.dartlang.org/packages/back_button_interceptor
Uwaga: jestem autorem tego pakietu.
źródło
Chociaż odpowiedź Remiego jest prawidłowa, zwykle nie chcesz po prostu blokować przycisku Wstecz, ale chcesz, aby użytkownik potwierdził wyjście.
Możesz to zrobić w podobny sposób, uzyskując odpowiedź z okna dialogowego potwierdzenia, ponieważ
onWillPop
to przyszłość.@override Widget build(BuildContext context) { return WillPopScope( child: Scaffold(...), onWillPop: () => showDialog<bool>( context: context, builder: (c) => AlertDialog( title: Text('Warning'), content: Text('Do you really want to exit'), actions: [ FlatButton( child: Text('Yes'), onPressed: () => Navigator.pop(c, true), ), FlatButton( child: Text('No'), onPressed: () => Navigator.pop(c, false), ), ], ), ), ); }
źródło
Publikuję to tutaj, na wypadek, gdyby ktoś to znalazł i chciałby znaleźć prosty przykład 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<BackButtonOverrideDemoWidget> with WidgetsBindingObserver{ //-------------------------Test Variable bool isBackButtonActivated = false; //-------------------------Required For WidgetsBindingObserver @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } //-------------------------Function That Triggers when you hit the back key @override didPopRoute(){ bool override; if(isBackButtonActivated) override = false; else override = true; return new Future<bool>.value(override); } //-------------------------Build Method @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("DeActive the Back Button") : new Text("Activate the Back Button"), ) ) ), ); } }
źródło
Możesz użyć
Future.value(bool)
do obsługi przycisku Wstecz.bool _allow = true; @override Widget build(BuildContext context) { return WillPopScope( child: Scaffold(appBar: AppBar(title: Text("Back"))), onWillPop: () { return Future.value(_allow); // if true allow back else block it }, ); }
źródło
onWillPop: () async => _allow
.Future.value()
rozmową.Użyłem mixin i widżetu WillPopScope po prostu nie mogłem wykonać tej pracy za mnie. To najlepsze podejście, które znalazłem, znacznie lepsze niż WillPopScope.
final bool canPop = ModalRoute.of(context)?.canPop ?? false;
Użyłem tego w następujący sposób na pasku aplikacji:
leading: ModalRoute.of(context)?.canPop ?? false ? IconButton( onPressed: () { Navigator.pop(context); }, icon: (Platform.isAndroid) ? const Icon(Icons.arrow_back) : const Icon(Icons.arrow_back_ios), ) : Container(),
źródło
Odpowiedź może wiedziałeś, że to użycie WillPopScope , ale niestety na IOS nie możesz przesunąć palcem do poprzedniej strony, więc dostosujmy twoją MaterialPageRoute:
class CustomMaterialPageRoute<T> extends MaterialPageRoute<T> { @protected bool get hasScopedWillPopCallback { return false; } CustomMaterialPageRoute({ @required WidgetBuilder builder, RouteSettings settings, bool maintainState = true, bool fullscreenDialog = false, }) : super( builder: builder, settings: settings, maintainState: maintainState, fullscreenDialog: fullscreenDialog, ); }
Teraz możesz użyć WillPopScope i przesunąć palcem do tyłu będzie działać na IOS. Odpowiedź na szczegóły jest tutaj: https://github.com/flutter/flutter/issues/14203#issuecomment-540663717
źródło
Po prostu dodaj kontener na początku paska aplikacji, który ukrywa przycisk Wstecz.
AppBar( title: new Text('Page Title'), leading: new Container(), ),
źródło