【问题标题】:Reload color container to null erase TextField inside Flutter重新加载颜色容器以清除 Flutter 中的 TextField
【发布时间】:2021-11-18 02:30:04
【问题描述】:

我有一个ContainerCupertinoTextField 包裹在Stack 中。

当我在文本字段上写完后,我按下一个按钮并用FocusNode 清除焦点,然后重新加载 UI。

我想为一个用例将颜色容器重新加载为 null,但是当我重新加载时,文本字段似乎“已删除”。然后,当我再次单击 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",
                    ),
                  ),
                )),
          ],
        ),
      ),
    );
  }
}

为什么会这样?以及如何解决?

【问题讨论】:

  • @pskink 感谢您的回复。根据answers & cmets,我意识到我以错误的方式提出了这个问题,这不是我所期望的。我知道如何以多种方式在图像上应用过滤器。我必须以不同的方式重新询问
  • @pskink 谢谢,这正是我想要的。如果你愿意,我可以重新写一个问题并接受你的代码。我可以看到您正在为孩子设置动画以模仿我的行为,尽管这将是代码重载,但我错了。再次感谢非常有用
  • 完成了,谢谢。我正在尝试在视频上做同样的事情,但我必须使用 FFmpeg 来应用过滤器,然后我想它也不能用这种方式完成?否则只在上方移动覆盖颜色,稍后在选择应用时检索它
  • 我不知道FFmpeg是如何在flutter上实现的......

标签: flutter dart containers focus setstate


【解决方案1】:

什么问题

Container 使用ColoredBox 来显示颜色。然而ColoredBox必须有颜色,所以实际上Container使用ColoredBox只有如果color!=null

它为您提供以下小部件树:

  • color!=null:[Container -&gt; ColoredBox -&gt; Stack]
  • color==null:[Container -&gt; Stack]

现在如果你知道 Flutter 状态是如何工作的,你就会知道如果同一级别的小部件树没有改变,一个状态会重新附加到同一个小部件上。在这里,由于CupertinoTextField 上方的小部件树发生了变化(ColoredBoxStack 替换,反之亦然),当颜色变为 null 或停止为 null 时,状态无法正确重建。

下面是详细内容

  1. 第一次聚焦 TextField 时,您的颜色不为空,小部件树不会改变,一切正常。
  2. 当您取消焦点时,小部件树会被修改,因此您的 TextField 状态丢失 => 文本为“重置”
  3. 当您重新聚焦时,小部件树再次更改,因此您的TextField 再次更改,导致键盘关闭
  4. 你回到了 1

有关 Flutter 键的更多信息,请参阅:When to Use Keys

如何解决

关键(:o)是让flutter明白Container下面的StackColoredBox下面的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有挑战性,我不知道也找不到。

有人认为这会很有趣!

【讨论】:

  • 非常感谢您的解释
猜你喜欢
  • 1970-01-01
  • 2021-09-28
  • 2020-09-26
  • 2020-08-26
  • 1970-01-01
  • 2016-04-19
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
相关资源
最近更新 更多