#flutter
Вопрос:
У меня есть ситуация, когда у меня есть два набора widgets
. Оба набора являются детьми stack
А. И я условно показываю второй набор виджетов во stateful widget
всплывающем окне. И мое требование заключается в том, что когда появляется всплывающее окно, его потомки фокусируются, а не виджет фона, и когда он не отображается, фон снова фокусируется.
Приведенный ниже код почти работает. Я использую FocusScope
виджет, чтобы ограничить фокус. Но проблема в том, что, когда всплывающее окно не отображается, фон TextField
не восстанавливает фокус. (мне приходится вручную нажимать TextField
или нажимать вкладку, чтобы вернуть фокус).
Пожалуйста, взгляните на код.
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'))
],
),
);
}
}
Спасибо.
Комментарии:
1. На этот вопрос трудно ответить? Я думаю, вы, ребята, должны уметь летать… Есть ли какая-то путаница в моем вопросе?
Ответ №1:
Вы меняете состояние (скрываете всплывающее окно) и фокусируетесь в одном и том же цикле кадра/сборки, что обычно не работает. Вы можете использовать обратный вызов после кадра или любую другую форму отложенного выполнения.
void _onPressPopup() {
setState(() {
_show = false;
});
WidgetsBinding.instance!.addPostFrameCallback((_) => _normalFN.requestFocus());
}
Комментарии:
1.
scheduleMicrotask
здесь хорошо работает