简体   繁体   English

根据 TextField state 更改 TextField 背景颜色

[英]Change TextField background Color based on the TextField state

I am currently trying to implement a TextField that should change the background Color-based on the state of the Text Field (unfocused, focused, error).我目前正在尝试实现一个 TextField,它应该根据文本字段的 state 更改背景颜色(未聚焦,聚焦,错误)。

I have tried to implement this by using a List that manages only whether the TextField is selected or not.我试图通过使用仅管理是否选择 TextField 的 List 来实现这一点。 I use a GestureDetector to set that value.我使用 GestureDetector 来设置该值。 But this seems way too hacky to be a good solution, especially because tapping on the TextField isn't the only way to focus it.但这似乎太老套了,不能成为一个好的解决方案,尤其是因为点击 TextField 并不是集中注意力的唯一方法。

At this point, I was hoping that there is a way to get the same information the TextField Widget uses to display the appropriate border style.在这一点上,我希望有一种方法可以获取 TextField Widget 用来显示适当边框样式的相同信息。 But I am not sure if it is possible to access this information.但我不确定是否可以访问这些信息。 A tip on how to do so would be highly appreciated.非常感谢您提供有关如何执行此操作的提示。

I was also thinking that I could use the FocusScope for this, but I could not find a way to call.hasFocus on a single TextFormField, because it only shows me whether one TextFormField in the whole Form is selected and not which one.我也在想我可以为此使用 FocusScope,但我找不到在单个 TextFormField 上调用.hasFocus 的方法,因为它只显示是否选择了整个表单中的一个 TextFormField,而不是选择哪个。

Thank you!谢谢!

You can either use FocusNode or Focus inside a FocusScope to achieve something like this.您可以在FocusScope中使用FocusNodeFocus来实现类似的效果。 TextField itself uses a FocusNode to determine if it has focus or not and then animates the color changes when the focus state changes. TextField本身使用一个FocusNode来确定它是否有焦点,然后在焦点 state 发生变化时动画颜色变化。 Here is an example implementation using Focus and a Builder to rebuild only the TextFields which changed focus:这是使用FocusBuilder仅重建更改焦点的TextFields的示例实现:

https://dartpad.dev/8488f470b166e4235b64d3ba568b6ba6?null_safety=true https://dartpad.dev/8488f470b166e4235b64d3ba568b6ba6?null_safety=true

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

/// This is the main application widget.
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const MyStatelessWidget(),
      ),
    );
  }
}
/// This is the private State class that goes with MyStatefulWidget.
class MyStatelessWidget extends StatelessWidget {
  
  const MyStatelessWidget();
  
  @override
  Widget build(BuildContext context) {
    return FocusScope(
      debugLabel: 'Scope',
      autofocus: true,
      child: Form(
        child: Column(
          children: [
            Focus(
              debugLabel: 'TextField1',
              child: Builder(
                builder: (BuildContext context) {
                  final FocusNode focusNode = Focus.of(context);
                  final bool hasFocus = focusNode.hasFocus;
                  return TextField(
                    decoration: InputDecoration(
                      fillColor: hasFocus ? Colors.green : Colors.white,
                      filled: true
                    )
                  );
                },
              ),
            ),
            Focus(
              debugLabel: 'TextField2',
              child: Builder(
                builder: (BuildContext context) {
                  final FocusNode focusNode = Focus.of(context);
                  final bool hasFocus = focusNode.hasFocus;
                  return TextField(
                    decoration: InputDecoration(
                      fillColor: hasFocus ? Colors.green : Colors.white,
                      filled: true
                    )
                  );
                }
              )
            )
          ],
        ),
      ),
    );
  }
}

You can of course also directly use a FocusNode .您当然也可以直接使用FocusNode For that you probably would have to wrap the TextFields into a StatefulWidget and then add a listener to the FocusNode used, so that you can trigger a rebuild (with setState ) when the focus changes.为此,您可能必须将TextFields包装到StatefulWidget中,然后向所使用的FocusNode添加一个侦听器,以便在焦点更改时触发重建(使用setState )。 But be aware that you need to manage the lifecycle of this FocusNode .但请注意,您需要管理此FocusNode的生命周期。 Quote from the documentation:从文档中引用:

Managing a FocusNode means managing its lifecycle, listening for changes in focus, and re-parenting it when needed to keep the focus hierarchy in sync with the widget hierarchy.管理 FocusNode 意味着管理它的生命周期,监听焦点的变化,并在需要时重新设置它的父节点,以保持焦点层次结构与小部件层次结构同步。 This widget does all of those things for you.这个小部件为您完成所有这些事情。 See FocusNode for more information about the details of what node management entails if you are not using a Focus widget and you need to do it yourself.如果您不使用 Focus 小部件并且需要自己进行操作,请参阅 FocusNode 以获取有关节点管理所需的详细信息的更多信息。

https://api.flutter.dev/flutter/widgets/Focus-class.html https://api.flutter.dev/flutter/widgets/Focus-class.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM