我正在尝试在运行时创建的TextField上调用requestFocus方法,但是函数callFocus((仅在我设置2秒的延迟时才起作用,可能是因为TextField是异步创建的。问题是,在 TextField 准备就绪后如何调用请求焦点?
appBar: AppBar(
title: appBarTitle,
centerTitle: true,
actions: <Widget>[
Center(
child: IconButton(
icon: actionIcon,
onPressed: () {
setState(() {
if (this.actionIcon.icon == Icons.search) {
this.actionIcon = Icon(Icons.navigate_next);
this.appBarTitle = TextField(
controller: editingController,
focusNode: _searchInsideFocus,
onChanged: (findNext) {
webView.findAllAsync(find: findNext);
},
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
border: UnderlineInputBorder(
borderSide: BorderSide.none),
prefixIcon: Icon(Icons.search, color: Colors.white),
hintText: "Search...",
hintStyle: TextStyle(color: Colors.white)),
).;
} else {
webView.findNext(forward: true);
}
});
callFocus();
},
),
),
)
Future<Null> callFocus() async {
await new Future.delayed(const Duration(seconds : 2)); //only works if delayed
FocusScope.of(context).requestFocus(_searchInsideFocus);
}
问题是没有来自父小部件的回调,允许您知道文本字段何时呈现,如果它以这种方式动态添加到树中。相反,只需将焦点请求移动到一个新的包装器小部件中,该小部件确实知道它何时首次渲染,因此可以在渲染发生后请求焦点,如下所示:
import 'package:flutter/material.dart';
class TextWrapper extends StatefulWidget {
const TextWrapper({
this.controller,
this.focusNode,
this.onChanged,
});
final TextEditingController controller;
final FocusNode focusNode;
final ValueChanged<String> onChanged;
@override
_TextWrapperState createState() => _TextWrapperState();
}
class _TextWrapperState extends State<TextWrapper> {
@override
Widget build(BuildContext context) {
return TextField(
controller: widget.controller,
focusNode: widget.focusNode,
onChanged: widget.onChanged,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
border: const UnderlineInputBorder(
borderSide: BorderSide.none,
),
prefixIcon: Icon(Icons.search, color: Colors.white),
hintText: 'Search...',
hintStyle: TextStyle(color: Colors.white),
),
);
}
void _onRendered(Duration _) {
FocusScope.of(context).requestFocus(widget.focusNode);
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback(_onRendered);
}
}
然后在您的Scaffold()
中执行此操作:
appBar: AppBar(
title: appBarTitle,
centerTitle: true,
actions: <Widget>[
Center(
child: IconButton(
icon: actionIcon,
onPressed: () {
setState(() {
if (this.actionIcon.icon == Icons.search) {
this.actionIcon = Icon(Icons.navigate_next);
this.appBarTitle = TextWrapper(
controller: editingController,
focusNode: _searchInsideFocus,
onChanged: (findNext) {
webView.findAllAsync(find: findNext);
},
);
} else {
webView.findNext(forward: true);
}
});
},
),
),
],
),
希望有帮助...
我相信焦点不会立即转移,因为在状态突变后,颤振引擎试图在更改状态小部件之前恢复对活动状态的关注(即IconButton
(。如果具有焦点的新状态小部件消失了,则具有autofocus
属性true
的下一个小部件将处于活动状态。
此行为值得使用。只需将文本字段的autofocus
属性设置为true
并单击后删除按钮:
import 'package:flutter/material.dart';
class LabPage extends StatefulWidget {
@override
_LabPageState createState() => _LabPageState();
}
class _LabPageState extends State<LabPage> {
bool inSearch = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: inSearch
? TextField(
autofocus: true,
onChanged: (findNext) {
// webView.findAllAsync(find: findNext);
},
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
border: UnderlineInputBorder(borderSide: BorderSide.none),
prefixIcon: Icon(Icons.search, color: Colors.white),
hintText: "Search...",
hintStyle: TextStyle(color: Colors.white)),
)
: Text('My App Title'),
centerTitle: true,
actions: <Widget>[
inSearch
? Container()
: Center(
child: IconButton(
icon: Icon(Icons.search),
onPressed: () {
setState(() {
inSearch = true;
});
},
),
),
]),
body: Container(),
);
}
}