重新加载颜色容器以空擦除 Flutter 中的 TextField
Reload color container to null erase TextField inside Flutter
我有一个 Container
在 Stack
内包装了一个 CupertinoTextField
。
当我在文本字段上完成书写时,我按下一个按钮并使用 FocusNode
清除焦点,然后重新加载 UI。
对于一个用例,我想将颜色容器重新加载为 null,但是当我重新加载时,文本字段似乎 'erased'。然后,当我再次点击 textfield 时,某些东西挡住了 textfield 。只有在第二次点击时,我才能检索文本字段焦点。
这是我上面描述的预览:
这是完整的代码:
class EditorTextPage extends StatefulWidget {
const EditorTextPage({Key? key}) : super(key: key);
@override
_EditorTextPageState createState() => _EditorTextPageState();
}
class _EditorTextPageState extends State<EditorTextPage> {
FocusNode focus = FocusNode();
bool displayEditor = true;
@override
void initState() {
focus.addListener(() {
if (focus.hasFocus) {
setState(() {
displayEditor = true;
});
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
color: displayEditor ? Colors.red : null,
child: SafeArea(
bottom: false,
child: Stack(
children: [
Positioned(
top: 100,
left: 200,
child: IntrinsicWidth(
child: CupertinoTextField(
focusNode: focus,
minLines: 1,
maxLines: 3,
padding: EdgeInsets.all(10),
cursorColor: Colors.white,
decoration: BoxDecoration(color: Colors.lightBlueAccent),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(bottom: 50),
child: CupertinoButton(
color: Colors.black,
onPressed: () {
setState(() {
if (focus.hasFocus) {
focus.unfocus();
displayEditor = false;
}
});
},
child: Text(
"DONE",
),
),
)),
],
),
),
);
}
}
为什么会这样?以及如何修复它?
问题是什么
Container
使用 ColoredBox
来显示颜色。然而 ColoredBox
必须 有颜色,所以实际上 Container
使用 ColoredBox
只有 if color!=null
.
这会为您提供以下小部件树:
- 与
color!=null
:[Container -> ColoredBox -> Stack]
- 与
color==null
:[Container -> Stack]
现在如果你知道 flutter state 是如何工作的,你就会知道如果同一级别的 widget 树不发生变化,一个 state 会重新附加到同一个 widget。在这里,由于 CupertinoTextField
上方的小部件树发生了变化(ColoredBox
被 Stack
替换,反之亦然),当颜色变为 null 或不再为 null 时,状态无法正确重建。
下面是详细情况
- 第一次聚焦时
TextField
你的颜色不为空,小部件树没有改变,一切正常。
- 当您失去焦点时,小部件树会被修改,因此您的
TextField
状态会丢失 => 文本为“重置”
- 当您重新聚焦时,小部件树再次发生变化,因此您的
TextField
再次发生变化,导致键盘关闭
- 你回到了 1
有关 Flutter 键的更多信息,请参阅:When to Use Keys
如何解决
关键(:o)是让flutter明白Container
下面的Stack
和ColoredBox
下面的是一样的。为此,请为其分配一个 GlobalKey
(如果您不明白为什么,请参阅我给您的视频)。
实现如下:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: EditorTextPage()));
}
class EditorTextPage extends StatefulWidget {
const EditorTextPage({Key? key}) : super(key: key);
@override
_EditorTextPageState createState() => _EditorTextPageState();
}
class _EditorTextPageState extends State<EditorTextPage> {
final focus = FocusNode();
bool displayEditor = true;
final _key = GlobalKey();
@override
void initState() {
focus.addListener(() {
if (focus.hasFocus) {
setState(() {
focus.requestFocus();
displayEditor = true;
});
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: displayEditor ? Colors.red : null,
child: SafeArea(
bottom: false,
child: Stack(
key: _key,
children: [
Positioned(
top: 100,
left: 200,
child: IntrinsicWidth(
child: CupertinoTextField(
focusNode: focus,
minLines: 1,
maxLines: 3,
padding: EdgeInsets.all(10),
cursorColor: Colors.white,
decoration: BoxDecoration(color: Colors.lightBlueAccent),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(bottom: 50),
child: CupertinoButton(
color: Colors.black,
onPressed: () {
if (focus.hasFocus) {
setState(() {
focus.unfocus();
displayEditor = false;
});
}
},
child: Text(
"DONE",
),
),
),
),
],
),
),
),
);
}
}
感谢您的挑战,这真的很有趣!
想要另一个没有密钥的修复程序吗?
另一种选择是避免完全修改小部件树。因此,解决方案是颜色永远不会为空,例如将其设置为透明:
// GOOD
color: displayEditor ? Colors.red : Colors.transparent
// BAD
color: displayEditor ? Colors.red : null
用什么?
我不知道。
第一个选项挑战flutter树算法
第二个选项是渲染透明色是否对flutter有挑战,这个我不知道也找不到。
有人认为这会很有趣!
我有一个 Container
在 Stack
内包装了一个 CupertinoTextField
。
当我在文本字段上完成书写时,我按下一个按钮并使用 FocusNode
清除焦点,然后重新加载 UI。
对于一个用例,我想将颜色容器重新加载为 null,但是当我重新加载时,文本字段似乎 'erased'。然后,当我再次点击 textfield 时,某些东西挡住了 textfield 。只有在第二次点击时,我才能检索文本字段焦点。
这是我上面描述的预览:
这是完整的代码:
class EditorTextPage extends StatefulWidget {
const EditorTextPage({Key? key}) : super(key: key);
@override
_EditorTextPageState createState() => _EditorTextPageState();
}
class _EditorTextPageState extends State<EditorTextPage> {
FocusNode focus = FocusNode();
bool displayEditor = true;
@override
void initState() {
focus.addListener(() {
if (focus.hasFocus) {
setState(() {
displayEditor = true;
});
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
color: displayEditor ? Colors.red : null,
child: SafeArea(
bottom: false,
child: Stack(
children: [
Positioned(
top: 100,
left: 200,
child: IntrinsicWidth(
child: CupertinoTextField(
focusNode: focus,
minLines: 1,
maxLines: 3,
padding: EdgeInsets.all(10),
cursorColor: Colors.white,
decoration: BoxDecoration(color: Colors.lightBlueAccent),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(bottom: 50),
child: CupertinoButton(
color: Colors.black,
onPressed: () {
setState(() {
if (focus.hasFocus) {
focus.unfocus();
displayEditor = false;
}
});
},
child: Text(
"DONE",
),
),
)),
],
),
),
);
}
}
为什么会这样?以及如何修复它?
问题是什么
Container
使用 ColoredBox
来显示颜色。然而 ColoredBox
必须 有颜色,所以实际上 Container
使用 ColoredBox
只有 if color!=null
.
这会为您提供以下小部件树:
- 与
color!=null
:[Container -> ColoredBox -> Stack]
- 与
color==null
:[Container -> Stack]
现在如果你知道 flutter state 是如何工作的,你就会知道如果同一级别的 widget 树不发生变化,一个 state 会重新附加到同一个 widget。在这里,由于 CupertinoTextField
上方的小部件树发生了变化(ColoredBox
被 Stack
替换,反之亦然),当颜色变为 null 或不再为 null 时,状态无法正确重建。
下面是详细情况
- 第一次聚焦时
TextField
你的颜色不为空,小部件树没有改变,一切正常。 - 当您失去焦点时,小部件树会被修改,因此您的
TextField
状态会丢失 => 文本为“重置” - 当您重新聚焦时,小部件树再次发生变化,因此您的
TextField
再次发生变化,导致键盘关闭 - 你回到了 1
有关 Flutter 键的更多信息,请参阅:When to Use Keys
如何解决
关键(:o)是让flutter明白Container
下面的Stack
和ColoredBox
下面的是一样的。为此,请为其分配一个 GlobalKey
(如果您不明白为什么,请参阅我给您的视频)。
实现如下:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: EditorTextPage()));
}
class EditorTextPage extends StatefulWidget {
const EditorTextPage({Key? key}) : super(key: key);
@override
_EditorTextPageState createState() => _EditorTextPageState();
}
class _EditorTextPageState extends State<EditorTextPage> {
final focus = FocusNode();
bool displayEditor = true;
final _key = GlobalKey();
@override
void initState() {
focus.addListener(() {
if (focus.hasFocus) {
setState(() {
focus.requestFocus();
displayEditor = true;
});
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: displayEditor ? Colors.red : null,
child: SafeArea(
bottom: false,
child: Stack(
key: _key,
children: [
Positioned(
top: 100,
left: 200,
child: IntrinsicWidth(
child: CupertinoTextField(
focusNode: focus,
minLines: 1,
maxLines: 3,
padding: EdgeInsets.all(10),
cursorColor: Colors.white,
decoration: BoxDecoration(color: Colors.lightBlueAccent),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(bottom: 50),
child: CupertinoButton(
color: Colors.black,
onPressed: () {
if (focus.hasFocus) {
setState(() {
focus.unfocus();
displayEditor = false;
});
}
},
child: Text(
"DONE",
),
),
),
),
],
),
),
),
);
}
}
感谢您的挑战,这真的很有趣!
想要另一个没有密钥的修复程序吗?
另一种选择是避免完全修改小部件树。因此,解决方案是颜色永远不会为空,例如将其设置为透明:
// GOOD
color: displayEditor ? Colors.red : Colors.transparent
// BAD
color: displayEditor ? Colors.red : null
用什么?
我不知道。
第一个选项挑战flutter树算法
第二个选项是渲染透明色是否对flutter有挑战,这个我不知道也找不到。
有人认为这会很有趣!