当我打开对话框时,应用程序会自动聚焦最新的文本字段



>我正在尝试创建一个主要关注为 PWA 的 Flutter 应用程序。我遇到了一些问题,例如...

当用户在安卓设备中点击后退按钮时,我们需要监听此操作并取消聚焦文本字段,如果您不这样做......键盘将不断出现。

  • 发现我只需要在主级别中包装下面的代码:

    Listener( onPointerDown: (_) { FocusScopeNode currentFocus = FocusScope.of(context); if (!currentFocus.hasPrimaryFocus) { print('unfocus'); currentFocus.focusedChild?.取消焦点();} }, child: MaterialApp(

是的!一切显然都正常工作,但是...当用户首先选择一个文本字段,然后点击一个按钮"如何包含对话框"时,键盘出现不到一秒钟,显然非常烦人。

我可以用下面的代码重现我的问题:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@OverRide
Widget build(BuildContext context) {
return Listener(
onPointerDown: (_) {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
print('unfocus');
currentFocus.focusedChild?.unfocus();
}
},
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@OverRide
State createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
@OverRide
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
children: [
FocusScope(
child: Focus(
onFocusChange: (focus) async {
print('$focus new');
},
child: const TextField())),
const SizedBox(
height: 10,
),
FocusScope(
child: Focus(
onFocusChange: (focus) async {
print(focus);
if (focus) {
final nowDate = DateTime.now();
final selectedDate = await showDatePicker(
context: context,
initialDate: nowDate,
firstDate: DateTime(1900),
lastDate: nowDate,
);
FocusManager.instance.primaryFocus?.unfocus();
if (selectedDate != null) {}
}
},
child: const TextField(
readOnly: true,
),
),
),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
FocusManager.instance.primaryFocus?.unfocus();
showDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
actions: [
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: const Text(
'Accept',
),
),
],
),
);
},
child: const Text('Submitted'),
)
],
),
),
);
}
}

如果您想重现我的问题,只需选择显示日期选择器的文本字段,然后按按钮,您将看到一个对话框,并在该小部件顶部另一个日期时间选择器...

如果分析代码,是简单的文本字段上的行为相同,当您按下按钮时,焦点会回到所选的最新文本字段...我发现避免此问题的唯一方法是旧解决方案,例如:

ElevatedButton(
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
showDialog(
context: context,
builder: (context) => CupertinoAlertDialog(
actions: [
ElevatedButton(
onPressed: () => Navigator.pop(context),
child: const Text(
'Accept',
),
),
],
),
);
},
child: const Text('Submitted'),
)

但可以肯定的是,这不是最佳解决方案。因此,如您所见,当对话框打开时,选择的最新文本字段是自动对焦,其结果是Flutter Web Mobile中的键盘错误。我不能使用第三方软件包,因为它们不支持网络。

你能告诉我我做错了什么吗?或者我怎样才能避免这个问题?这是一个颤振问题吗?

当用户在Android设备中点击后退按钮时,如果您不这样做 这。。。键盘将不断出现。

  • 每次我们离开屏幕或页面时,请确保处理掉所有控制器。 为了避免内存泄漏,并且与您的问题相同,文本字段控制器尚未释放。 这就是为什么当您按下后退按钮时,它仍然会出现。
@override
void dispose() {
yourTextController.dispose();
super.dispose();
}
  • 我不建议你MaterialApp
Listener( onPointerDown: (_) { FocusScopeNode currentFocus = FocusScope.of(context);

即:当您点击任何屏幕中的任何位置时,您将执行focusNode. 当您的屏幕没有任何文本字段时包含。 我认为您只能包装当前屏幕。

最新更新