Flutter 如何在键盘打开的情况下按下 Android 上的后退按钮时隐藏 AlertDialog

问题描述 投票:0回答:1

我有一个带有自动对焦文本字段的警报对话框,因此当警报对话框打开时,键盘会自动打开。但是,如果我在 Android 上按后退按钮,则只会关闭键盘,并且我需要再次按后退按钮才能关闭对话框。 我在 TextField 的 OnSubscribed 回调中具有所需的行为,其中我只使用 Navigator.pop(context)。但我认为这是有效的,因为我只是关闭了警报对话框,键盘也随之关闭,因为没有文本可以填充了。但是,当我按“后退”按钮时,我无法在“文本字段”或“警报对话框”中跟踪它,因此无法使用 Navigator.pop(context)。 我尝试在警报对话框、Scaffold 甚至 MaterialApp 上使用 PopScope - 它不会记录第 1 次后退按钮按下,仅记录第 2 次按下。我还尝试使用 KeyboardListener 来查找 BackButton 操作按下,但我可以让它工作。

我认为这是因为关闭键盘不会改变 TextField 的焦点,并且无法使用 PopScope 或其他方法捕获。 这是我设法使其工作的方法,但我认为这太长了并且这依赖于键盘动画。如果它更长 - 这将不起作用。

在这里,我确保窗口仅关闭一次,因为它尝试调用 Navigator.pop(context) 两次,并且它只是关闭整个应用程序页面本身并将其变为黑色。

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:todo_app/utils/global_utils.dart' as globals;

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

  @override
  State<BasicWindow> createState() => _BasicWindowState();
}

class _BasicWindowState extends State<BasicWindow> {
  @override
  Widget build(BuildContext context) {
    //make sure the build is finished 
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (!mounted) return;
      if (globals.mobile) {
        Future.delayed(const Duration(milliseconds: 400), () {
          bool noKeyboardShown =
              MediaQuery.of(context).viewInsets.bottom == 0.0;
          if (noKeyboardShown & !globals.dialogClosed) {
            globals.dialogClosed = true;
            Navigator.pop(context);
            Future.delayed(const Duration(milliseconds: 600), () {
              globals.dialogClosed = false;
            });
          }
        });
      }
    });

    return AlertDialog(
      content: TextField(
        //focusNode: _textFocus,
        onSubmitted: (value) {
          Navigator.pop(context);
        },
        
      ),
    );
  }
}
android flutter dart
1个回答
0
投票

您必须使用

WillPopScope
来实现此行为。 像这样重构你的代码:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:todo_app/utils/global_utils.dart' as globals;

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

  @override
  State<BasicWindow> createState() => _BasicWindowState();
}

class _BasicWindowState extends State<BasicWindow> {
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        // Close the keyboard before popping the dialog
        FocusScope.of(context).unfocus();
        
        // Close the dialog
        if (!globals.dialogClosed) {
          globals.dialogClosed = true;
          Navigator.pop(context);
          // Reset the dialogClosed flag after a delay to prevent re-triggering
          Future.delayed(const Duration(milliseconds: 600), () {
            globals.dialogClosed = false;
          });
        }

        // Return true to allow the back action (closing the dialog)
        return false;
      },
      child: AlertDialog(
        content: TextField(
          autofocus: true,
          onSubmitted: (value) {
            Navigator.pop(context);
          },
        ),
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.