当canRequestFocus在颤振中发生变化时,如何自动对焦FocusScope的后代?



我有两组widgets。两个集合都是stack的子集合。我有条件地显示第二组小部件在stateful widget(弹出)。我的要求是,当弹出窗口显示时,它的后代是可聚焦的,而不是背景小部件的当它不显示时,背景重新获得焦点。

下面的代码几乎可以工作。我使用FocusScope小部件来限制焦点。但问题是,当弹出窗口不显示时,背景TextField没有恢复焦点。(我必须手动按TextField或按TAB键才能恢复焦点)。

请查看代码。

import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: const Material(child: MyHomePage()),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _show = false;
final _normalFN = FocusNode();
final _popupFN = FocusNode();
void _onPressNormal() {
setState(() {
_show = true;
_popupFN.requestFocus();
});
}
void _onPressPopup() {
setState(() {
_show = false;
_normalFN.requestFocus();
});
}
@override
void dispose() {
_normalFN.dispose();
_popupFN.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Stack(
alignment: Alignment.center,
children: [
FocusScope(
canRequestFocus: !_show,
child: Column(children: [
TextField(focusNode: _normalFN, autofocus: true),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _onPressNormal, child: const Text("open popUp")),
])),
if (_show) Popup(_onPressPopup, _popupFN),
],
),
);
}
}
class Popup extends StatelessWidget {
const Popup(this.onPress, this.focusNode, {Key? key}) : super(key: key);
final void Function() onPress;
final FocusNode focusNode;
@override
Widget build(BuildContext context) {
return Container(
color: Colors.yellow,
width: 300,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(focusNode: focusNode),
const SizedBox(height: 30),
ElevatedButton(onPressed: onPress, child: const Text('close'))
],
),
);
}
}

谢谢。

你在同一帧/构建循环中改变状态(隐藏弹出窗口)和焦点,这通常不起作用。你可以使用后帧回调或任何其他形式的延迟执行。

void _onPressPopup() {
setState(() {
_show = false;
});
WidgetsBinding.instance!.addPostFrameCallback((_) => _normalFN.requestFocus());
}

最新更新