Flutter'da Android "GERİ" düğmesini nasıl devre dışı bırakabilir veya geçersiz kılabilirsiniz?


114

Belirli bir sayfadayken Android geri düğmesini devre dışı bırakmanın bir yolu var mı?

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(),
      },
    );
  }
}

On pageOne İkinci sayfaya gitmek için bir düğmem var:

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

Benim sorunum, android ekranının altındaki Geri okuna basarsam, pageOne'a geri dönmem. Bu düğmenin hiç görünmemesini istiyorum. İdeal olarak, kullanıcı örneğin parmağını ekranda 5 saniye basılı tutmadıkça bu ekrandan çıkmanın mümkün olmamasını isterim. (Yeni yürümeye başlayan çocuklar için bir Uygulama yazmaya çalışıyorum ve yalnızca ebeveynlerin belirli bir ekrandan dışarı çıkabilmesini istiyorum).

Yanıtlar:


202

Cevap şudur WillPopScope. Sayfanın sistem tarafından açılmasını engelleyecektir. Hala kullanabileceksinizNavigator.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(),
        ),
      ),
    ),
  );
}

1
Bir Formun patlamasını engellemek isteyenler için, Form onWillPopözelliğini kullanmak daha uygundur . Form durumuna erişimi vardır ve önce kullanıcının kaybetmek istemeyebileceği herhangi bir durum olup olmadığını kontrol edebilir.
Joe Lapp

Merhaba @ RémiRousselet, Lütfen arka yığında bana bir yığın A, B, C, D ekranlarım varmış gibi yönetmeme yardım eder misiniz ve D-> B VEYA D-> A'dan gezinmek istiyorum, o zaman nasıl idare edeceğim o. Lütfen bana bu konuda rehberlik eder misiniz
Ravindra Kushwaha

Bu cevabın belki eski olduğunu biliyorum. Ama bir GEM! Açıklamayı genişletmeyi düşünün. Mükemmel çalışıyor. Teşekkür ederim.
Val

1
Pop () 'dan önce bir şeyler yapmak isteyen biri için bunu kullanabilironWillPop: () async { onBack(); // "DO YOUR FUNCTION IS HERE WHEN POP" return false; }
Huy Tower

24

Rémi Rousselet'in belirttiği gibi WillPopScope, genellikle gidilecek yol budur. Ancak, geri düğmesine doğrudan tepki vermesi gereken durum bilgisi olan bir pencere öğesi geliştiriyorsanız, bunu kullanabilirsiniz:

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

Not: Bu paketin yazarıyım.


Tüm saygımla, bunun bir yorum olarak daha uygun olduğunu düşünmüyor musun?
CopsOnRoad

26
@CopsOnRoad Hayır, çünkü bu başka bir cevaba yorum değil, aynı sorunu çözmenin tamamen farklı bir yolu.
MarcG

Bu iyi bir alternatif ve bir yorumun parçası olsaydı göz ardı edilebilirdi.
abhijat_saxena

18

Remi'nin cevabı doğru olsa da, genellikle geri düğmesini engellemek istemezsiniz, ancak bir kullanıcının çıkışı onaylamasını istersiniz.

Onay iletişim kutusundan bir cevap alarak benzer şekilde yapabilirsiniz, çünkü onWillPopbir gelecek.

@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),
          ),
        ],
      ),
    ),
  );
}

Bu cevap neden olumsuz oy alıyor? Bunu uygulayan ve kötü deneyime sahip olan var mı?
SamiAzar

Cihazdan geri tuşuna bastıktan sonra ilk ekrana gitmek yerine önceki ekrana gitmek istiyorum. Böyle bir iletişim kutusuna ihtiyacım yok. Ne yapmalıyım
LakshmiYogeshwaran

4

Bunu, herhangi birinin bunu bulması ve basit bir örnek bulmasını dilemesi durumunda buraya gönderiyorum 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"),
              )
          )
      ),
    );
  }
}

Dün gerçekten kendim kullandım. Yalnızca Android için olduğunu, Apple'ın geri düğmesi olmadığını unutmayın. Yine de bana neyin yanlış gittiğini söyleyebilirsin, böylece onu onarabilirim, ya da belki sadece benim özel öykünücümde çalışır. Flutterımı birkaç haftadır güncellemedim, bu yüzden belki de sorun budur.
Bryan İptal

@BryanCancel Cevabınız yalnızca henüz zorlanan rotalarınız yoksa işe yarar. WidgetsBinding.handlePopRoute () yöntemine bakın. Gözlemcilere kayıt sırasına göre bildirimde bulunur ve doğruyu alır almaz durur. Zorlanmış rotalar olduğunda, gezgin önce doğruya döner ve ardından gözlemciniz aslında hiçbir zaman çağrılmaz. Başka bir deyişle, kodunuz yalnızca kullanıcı geri düğmesine tıkladığında, başka rota kalmadığında uygulamanın kapanmasını önlemek için çalışır.
MarcG

3

Future.value(bool)Geri düğmesini kullanmak için kullanabilirsiniz .

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
    },
  );
}

Bilginize, bu eşdeğerdir onWillPop: () async => _allow.
Lynn

@Lynn evet bunu biliyorum. Sadece Future.value()aramayı paylaşmak istedim .
CopsOnRoad

3

Mixin kullandım ve WillPopScope widget'ı işi benim için yapamadı. Bu bulduğum en iyi yaklaşım, bence WillPopScope'tan çok daha iyi.
final bool canPop = ModalRoute.of(context)?.canPop ?? false;
Appbar içinde şu şekilde kullandım:

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(),

2

Cevap, belki de bu en kullanmak biliyordum WillPopScope , ama ne yazık üzerinde IOS sen olamaz geri tokatlamak o yüzden özel senin MaterialPageRoute izin Önceki sayfayı:

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,
        );
}

Artık WillPopScope'u kullanabilirsiniz ve geriye doğru hızlıca kaydırın IOS üzerinde çalışacaktır. Ayrıntıların cevabı burada: https://github.com/flutter/flutter/issues/14203#issuecomment-540663717


1

Appbar'ın başına geri düğmesini gizleyen bir kap eklemeniz yeterlidir.

AppBar(
        title: new Text('Page Title'),
        leading: new Container(),
      ),
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.