根据表单验证更改Flutter的TextFormField后缀图标颜色。

3

我正在尝试为TextFormField的后缀图标创建一个覆盖小部件。通常我们会使用ToolTip,但是我只是想尝试一些新的东西,因为覆盖小部件可以自定义。 我想在TextFormField的后缀图标没有通过验证时将其颜色从灰色更改为红色。 因此,当图标变为红色时,它会向用户发出警告,当用户单击它时,覆盖小部件将显示。
我的覆盖小部件代码。

void _showOverlay(BuildContext context) async {
    OverlayState? overlayState = Overlay.of(context);
    OverlayEntry overlayEntry;
    overlayEntry = OverlayEntry(builder: (context) {
      return Positioned(
        left: MediaQuery.of(context).size.width * 0.1,
        top: MediaQuery.of(context).size.height * 0.23,
        child: ClipRRect(
          borderRadius: BorderRadius.circular(10),
          child: Material(
            child: Container(
              alignment: Alignment.center,
              color: Colors.grey.shade200,
              padding:
                  EdgeInsets.all(MediaQuery.of(context).size.height * 0.02),
              width: MediaQuery.of(context).size.width * 0.8,
              height: MediaQuery.of(context).size.height * 0.06,
              child: const Text(
                'Name should be more than 2 characters',
                style: TextStyle(color: Colors.black),
              ),
            ),
          ),
        ),
      );
    });
    overlayState!.insert(overlayEntry);

    await Future.delayed(const Duration(seconds: 3));

    overlayEntry.remove();
  }

我的提交按钮方法:

void _submitForm() {
    setState(() {
      _autoValidateMode = AutovalidateMode.always;
    });
    final form = _formKey.currentState;
    if (form == null || !form.validate()) return;

    form.save();
    print(_name);
  }  

我的TextFormField小部件:

TextFormField(
                  controller: nameController,
                  keyboardType: TextInputType.name,
                  textInputAction: TextInputAction.next,
                  textCapitalization: TextCapitalization.words,
                  validator: (String? value) {
                    if (value == null || value.trim().isEmpty) {
                      return;
                    }
                    return null;
                  },
                  onSaved: (String? value) {
                    _name = value;
                  },
                  decoration: kTextInputDecoration.copyWith(
                      labelText: 'Full Name',
                      prefixIcon: const Icon(Icons.person),
                      suffixIcon: IconButton(
                          padding: EdgeInsets.zero,
                          onPressed: () {
                            _showOverlay(context);
                          },
                          icon: const Icon(
                            Icons.info,
                            color: Colors.grey //change icon color according to form validation 
                          ))),  

提交按钮。

ElevatedButton(
                    onPressed: () {
                      _submitForm();
                    },
                    style: ElevatedButton.styleFrom(
                        padding: const EdgeInsets.all(10)),
                    child: const Text(
                      'Submit',
                      style: TextStyle(fontSize: 20),
                    )),  

当提交按钮按下时,我想要改变后缀图标的颜色。如果表单未经验证,则颜色应更改为红色或默认为灰色。非常感谢您的帮助。

你能否包含一个简化的完整小部件来处理TextField吗? - Yeasin Sheikh
@YeasinSheikh 对不起,我没有理解你的意思。 - sulli110
我在考虑一个完整的小部件,而不需要 kTextInputDecoration,并且将包括表单小部件。 - Yeasin Sheikh
2个回答

0

警告:以下解决方案目前在稳定通道3.3.9上已经失效,但在beta版本中可以正常工作。
问题已于2022年8月23日标记为已修复,因此我有很大的希望我们很快就能在稳定版中得到它。

您可以:

  1. 创建一个扩展MaterialStateColor的类
  2. 在您的构建方法中基于您的主题创建一个实例
  3. 将该实例传递给suffixIconColor
class InfoIconColor extends MaterialStateColor {
  const InfoIconColor(
    super.defaultColor, {
    required this.disabledColor,
    required this.errorColor,
  });

  final Color disabledColor;
  final Color errorColor;

  @override
  Color resolve(Set<MaterialState> states) {
    if (states.contains(MaterialState.error)) return errorColor;
    if (states.contains(MaterialState.disabled)) return disabledColor;
    return Color(super.value);
  }
}

TextFormField(
  // ...
  decoration: kTextInputDecoration.copyWith(
    labelText: 'Full Name',
    suffixIcon: // ...
    suffixIconColor: // ...
  ),
)  

同时,您可以在应用程序的主题中使用相同的InfoIconColor(或者将您的小部件包装在一个主题小部件中),如下所示:

final theme = Theme.of(context); 
Theme(
  data: theme.copyWith(
    inputDecorationTheme: theme.inputDecorationTheme.copyWith(
      suffixIconColor: //...
    ),
  ),
  child: //...
)

-1
你可以创建一个布尔变量来存储验证结果,或者直接使用 validate 方法。
 ///state level
  bool _isValidate = true;
  ......
 /// inside TextFormField
validator: (String? value) {
  if (value == null || value.trim().isEmpty) {
    setState(() {
      _isValidate = false;
    });
    return "Error message";
  }
  return null;
},

onTap: () {
  setState(() {
    _isValidate = true;
  });
},


/// and Icon color 
icon: Icon(
  Icons.info,
  color: _isValidate ? Colors.grey : Colors.red,
),

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接