Flutter 如何正确聚焦基于焦点节点有条件创建的文本字段';它有焦点值吗?
使用我当前的代码,文本字段会聚焦,但光标和键盘不会被触发(需要再次点击)。我相信这是因为当焦点节点最初被聚焦时文本字段并不存在,但我正在努力寻找解决方案 以下是一个基于食谱的简单问题再现:Flutter 如何正确聚焦基于焦点节点有条件创建的文本字段';它有焦点值吗?,flutter,focus,textfield,listviewitem,Flutter,Focus,Textfield,Listviewitem,使用我当前的代码,文本字段会聚焦,但光标和键盘不会被触发(需要再次点击)。我相信这是因为当焦点节点最初被聚焦时文本字段并不存在,但我正在努力寻找解决方案 以下是一个基于食谱的简单问题再现: class MyCustomForm extends StatefulWidget { @override _MyCustomFormState createState() => _MyCustomFormState(); } class _MyCustomFormState extends
class MyCustomForm extends StatefulWidget {
@override
_MyCustomFormState createState() => _MyCustomFormState();
}
class _MyCustomFormState extends State<MyCustomForm> {
FocusNode myFocusNode;
bool _editingField2 = false;
@override
void initState() {
super.initState();
myFocusNode = FocusNode();
myFocusNode.addListener(_focusListener);
}
@override
void dispose() {
myFocusNode.dispose();
super.dispose();
}
// Set _editingField2 to true when focusNode has focus.
_focusListener() {
if (myFocusNode.hasFocus) {
setState(() {
_editingField2 = true;
});
} else {
setState(() {
_editingField2 = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Text Field Focus'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// The first text field is focused on as soon as the app starts.
TextField(
autofocus: true,
),
// The second text field is created when _editingField2 (after FAB press).
_editingField2
? TextField(
focusNode: myFocusNode,
)
: Text('ayy'),
],
),
),
floatingActionButton: FloatingActionButton(
// Give focus node focus on FAB press.
onPressed: () => FocusScope.of(context).requestFocus(myFocusNode),
tooltip: 'Focus Second Text Field',
child: Icon(Icons.edit),
),
);
}
}
类MyCustomForm扩展StatefulWidget{
@凌驾
_MyCustomFormState createState()=>\u MyCustomFormState();
}
类_MyCustomFormState扩展了状态{
黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性黏性;
bool_editingField2=假;
@凌驾
void initState(){
super.initState();
myFocusNode=FocusNode();
myFocusNode.addListener(_focusListener);
}
@凌驾
无效处置(){
myFocusNode.dispose();
super.dispose();
}
//当focusNode具有焦点时,将_editingField2设置为true。
_focusListener(){
if(myFocusNode.hasFocus){
设置状态(){
_编辑字段2=真;
});
}否则{
设置状态(){
_编辑字段2=假;
});
}
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(“文本字段焦点”),
),
主体:填充物(
填充:常数边集全部(16.0),
子:列(
儿童:[
//应用程序一启动,第一个文本字段就会被关注。
文本字段(
自动对焦:对,
),
//第二个文本字段是在编辑字段2时创建的(在按FAB键之后)。
_编辑字段2
?文本字段(
focusNode:myFocusNode,
)
:Text('ayy'),
],
),
),
浮动操作按钮:浮动操作按钮(
//将焦点节点焦点放在晶圆厂压力机上。
onPressed:()=>FocusScope.of(context).requestFocus(myFocusNode),
工具提示:“聚焦第二个文本字段”,
子:图标(Icons.edit),
),
);
}
}
这是我的代码,有重要的注释
class TaskListItem extends StatefulWidget {
final Task task;
TaskListItem({@required this.task});
@override
State createState() => _TaskListItemState();
}
class _TaskListItemState extends State<TaskListItem> {
bool _isEditing;
FocusNode _focusNode;
final TextEditingController _textEditingController = TextEditingController();
@override
initState() {
super.initState();
_isEditing = false;
_textEditingController.text = widget.task.text;
_textEditingController.addListener(_handleTextFieldUpdate);
_focusNode = FocusNode(debugLabel: 'TaskListItem');
_focusNode.addListener(_handleFocusChange);
}
@override
void dispose() {
_focusNode.removeListener(_handleFocusChange);
_focusNode.dispose();
_textEditingController.dispose();
super.dispose();
}
_handleTextFieldUpdate() {
Provider.of<TaskListModel>(context, listen: false)
.updateTaskText(widget.task, _textEditingController.text);
}
// Update state to determine if Text or TextField widget is created in build().
_handleFocusChange() {
if (_focusNode.hasFocus) {
setState(() {
_isEditing = true;
});
} else {
setState(() {
_isEditing = false;
});
}
}
Widget _buildTitle() {
return Row(
children: <Widget>[
Expanded(
// Create either TextField or Text based on _isEditing value.
child: _isEditing && !widget.task.isComplete
? TextField(
focusNode: _focusNode,
controller: _textEditingController,
)
: Text(
widget.task.text,
style: widget.task.isComplete
? TextStyle(decoration: TextDecoration.lineThrough)
: null,
),
),
],
);
}
@override
Widget build(BuildContext context) {
return ListTile(
leading: Checkbox(
value: widget.task.isComplete,
//Dismiss focus when box is checked
onChanged: (bool checked) {
_focusNode.unfocus();
Provider.of<TaskListModel>(context, listen: false)
.toggleComplete(widget.task);
},
),
title: _buildTitle(),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => Provider.of<TaskListModel>(context, listen: false)
.deleteTask(widget.task),
),
onTap: () {
// I'm requesting focus here, but the Textfield doesn't exist yet?
FocusScope.of(context).requestFocus(_focusNode);
print('tapped');
},
);
}
}
class TaskListItem扩展StatefulWidget{
最终任务;
TaskListItem({@required this.task});
@凌驾
State createState()=>\u TaskListItemState();
}
类_TaskListItemState扩展状态{
布卢伊塞丁;
FocusNode _FocusNode;
最终文本编辑控制器_TextEditingController=TextEditingController();
@凌驾
initState(){
super.initState();
_i编辑=假;
_textEditingController.text=widget.task.text;
_textEditingController.addListener(\u handleTextFieldUpdate);
_focusNode=focusNode(debugLabel:'TaskListItem');
_focusNode.addListener(_handleFocusChange);
}
@凌驾
无效处置(){
_focusNode.removeListener(_handleFocusChange);
_focusNode.dispose();
_textEditingController.dispose();
super.dispose();
}
_handleTextFieldUpdate(){
Provider.of(上下文,侦听:false)
.updateTaskText(widget.task,_textEditingController.text);
}
//更新状态以确定是否在build()中创建了文本或文本字段小部件。
_handleFocusChange(){
if(_focusNode.hasFocus){
设置状态(){
_i编辑=真;
});
}否则{
设置状态(){
_i编辑=假;
});
}
}
小部件_buildTitle(){
返回行(
儿童:[
扩大(
//根据编辑值创建文本字段或文本。
子项:_isEditing&!widget.task.isComplete
?文本字段(
focusNode:_focusNode,
控制器:_textededitingcontroller,
)
:文本(
widget.task.text,
样式:widget.task.isComplete
?TextStyle(装饰:textEdition.lineThrough)
:null,
),
),
],
);
}
@凌驾
小部件构建(构建上下文){
返回列表块(
前导:复选框(
值:widget.task.isComplete,
//选中此复选框时关闭焦点
一旦更改:(布尔检查){
_focusNode.unfocus();
Provider.of(上下文,侦听:false)
.toggleComplete(widget.task);
},
),
标题:_buildTitle(),
尾随:图标按钮(
图标:图标(Icons.delete),
onPressed:()=>Provider.of(上下文,侦听:false)
.deleteTask(widget.task),
),
onTap:(){
//我在这里请求焦点,但文本字段还不存在?
FocusScope.of(上下文).requestFocus(_focusNode);
打印(‘点击’);
},
);
}
}
您需要做的是在构建内部更改焦点,您正在尝试在屏幕已经重建该小部件之前更改焦点。请使用您自己的代码尝试此操作
我不确定您是否需要真正倾听焦点更改,或者您是否只想在启用小部件后完成焦点更改,如果您确实想倾听焦点更改,请告诉我
class MyCustomForm extends StatefulWidget {
@override
_MyCustomFormState createState() => _MyCustomFormState();
}
class _MyCustomFormState extends State<MyCustomForm> {
FocusNode myFocusNode = FocusNode();
bool _editingField2 = false;
@override
void dispose() {
myFocusNode?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
//here you do the focus request
if (_editingField2) {
FocusScope.of(context).requestFocus(myFocusNode);
}
return Scaffold(
appBar: AppBar(
title: Text('Text Field Focus'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// The first text field is focused on as soon as the app starts.
TextField(
autofocus: true,
),
// The second text field is created when _editingField2 (after FAB press).
_editingField2
? TextField(
focusNode: myFocusNode,
)
: Text('ayy'),
],
),
),
floatingActionButton: FloatingActionButton(
// Give focus node focus on FAB press.
onPressed: () {
setState(() {
_editingField2 = true;
});
},
tooltip: 'Focus Second Text Field',
child: Icon(Icons.edit),
),
);
}
}
类MyCustomForm扩展StatefulWidget{
@凌驾
_MyCustomFormState createState()=>\u MyCustomFormState();
}
类_MyCustomFormState扩展了状态{
FocusNode myFocusNode=FocusNode();
bool_editingField2=假;
@凌驾
无效处置(){
myFocusNode?.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
//在这里,您可以执行焦点请求
如果(编辑字段2){
FocusScope.of(上下文).requestFocus(myFocusNode);
}
返回脚手架(
appBar:appBar(
标题:文本(“文本字段焦点”),
),
主体:填充物(
填充:常数边集全部(16.0),
子:列(
儿童:[
//应用程序一启动,第一个文本字段就会被关注。
文本字段(
自动对焦:对,
),
//东南