PopScope не выходит из приложения и возвращает только пустой экран

Использование PopScope, чтобы убедиться, что пользователю нужно дважды нажать кнопку «Назад», чтобы выйти из приложения. Проблема в том, что после двойного нажатия кнопки «Назад» вместо выхода из приложения возвращается только пустой экран или пустой экран. Если я использую WillPopScope, все работает так, как задумано.

Я также должен убедиться, что мое приложение использует только 1 MaterialApp внутри приложения. Вопрос в том, как правильно реализовать такое поведение для Android и iOS?

Вот пример кода:

class RootScaffold extends StatefulWidget {
  final Widget body;

  const RootScaffold({required this.body, super.key});

  @override
  State<RootScaffold> createState() => _RootScaffoldState();
}

class _RootScaffoldState extends State<RootScaffold> {
  DateTime? lastBackPressTime;

  bool onWillPop() {
    DateTime now = DateTime.now();
    if (lastBackPressTime == null ||
        now.difference(lastBackPressTime!) > const Duration(seconds: 2)) {
      lastBackPressTime = now;
      Fluttertoast.showToast(msg: 'Press back again to exit.');
      return false;
    }

    return true;
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvoked: (bool didPop) async {
        if (didPop) {
          return;
        }

        final shouldPop = onWillPop();
        if (shouldPop && context.mounted) {
          Navigator.of(context).pop();
        }
      },
      child: Scaffold(body: widget.body),
    );
  }
}
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Здесь есть две проблемы. Я считаю, что на Android вашу проблему можно решить, но на iOS это может быть сложно.

Итак, для Android: измените Navigator.of(context).pop(); на SystemNavigator.pop();. Проблема здесь в том, что Navigator.of не может вызвать системную механику для выхода из приложения. Экран просто трепещет, поэтому вы видите белый экран.

Для iOS это не сработает, так как SystemNavigator.pop() ничего не сделает. Это задуманное поведение, поскольку оно противоречит рекомендациям Apple по дизайну: Apple рекомендует пользователям выходить из приложений с помощью кнопки «Домой» или жеста смахивания. Я думаю, что в этой ситуации правильный путь — ничего не делать на iOS.

Попробуйте создать метод onWillPop()Future<bool> и конструктор and использовать Future.value([FutureOr<T>? value]) для возврата значения.

Так :

class ClickAgainToCloseWidget extends StatefulWidget {
  const ClickAgainToCloseWidget({super.key});

  @override
  State<ClickAgainToCloseWidget> createState() =>
      _ClickAgainToCloseWidgetState();
}

class _ClickAgainToCloseWidgetState extends State<ClickAgainToCloseWidget> {
  DateTime? lastBackPressTime;

  Future<bool> onWillPop({int neededTime = 2, required String msgToast}) {
    DateTime now = DateTime.now();
    if (lastBackPressTime == null ||
        now.difference(lastBackPressTime!) >
            Duration(
              seconds: neededTime,
            )) {
      lastBackPressTime = now;
      Fluttertoast.showToast(msg: msgToast);
      return Future.value(false);
    }

    return Future.value(true);
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvoked: (bool didPop) async {
        if (didPop) {
          return;
        }

        final shouldPop =
            await onWillPop(msgToast: 'Press back again to exit.');
        if (shouldPop && context.mounted) {
          Navigator.of(context).pop();
        }
      },
      child: const Scaffold(
        body: Center(
          child: Text("Click Back Again To close"),
        ),
      ),
    );
  }
}

Другие вопросы по теме