如何为运行时创建的 TextField 调用 requestFocus?
How to call requestFocus for a TextField created at runtime?
我试图在运行时创建的 TextField 上调用 requestFocus 方法,但是函数 callFocus() 仅在我将延迟设置为 2 秒时才起作用,这可能是因为 TextField 是异步创建的。问题是,TextField准备好后,如何调用requestFocus?
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);
}
});
},
),
),
],
),
希望对您有所帮助...
我相信焦点不会立即转移,因为在状态突变之后,flutter 引擎会尝试在更改状态小部件(即 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(),
);
}
}
我试图在运行时创建的 TextField 上调用 requestFocus 方法,但是函数 callFocus() 仅在我将延迟设置为 2 秒时才起作用,这可能是因为 TextField 是异步创建的。问题是,TextField准备好后,如何调用requestFocus?
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);
}
});
},
),
),
],
),
希望对您有所帮助...
我相信焦点不会立即转移,因为在状态突变之后,flutter 引擎会尝试在更改状态小部件(即 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(),
);
}
}