简体   繁体   English

在颤振中,如何为 textformfield 自定义样式错误消息?

[英]In flutter, how to custom style error messages for textformfield?

My textformfield is styled in a way that is wrapped with a grey wrapping container to look differently when the field is in-focus.我的 textformfield 的样式是用灰色包装容器包装的,以便在该字段处于焦点时看起来不同。 However, it becomes bloated (increases in size) whenever there is an error message because the field is wrapped with that grey wrapping container.但是,每当出现错误消息时,它就会变得臃肿(大小增加),因为该字段是用那个灰色的包装容器包装的。

How do I custom style the error message outside of the grey wrapping container so that the textformfield doesn't bloat in size?如何在灰色包装容器之外自定义错误消息的样式,以使 textformfield 的大小不会膨胀?

Essentially I want the error message to be positioned outside of grey the wrapper container.本质上,我希望将错误消息定位在包装容器的灰色之外。

带有包装容器的臃肿文本框

@override Widget build(BuildContext context) {
final InputDecorationTheme inputTheme = Theme.of(context).inputDecorationTheme;

return Focus(
  canRequestFocus: false,
  child: Builder(builder: (context) {
    final FocusNode focusNode = Focus.of(context);
    final bool hasFocus = focusNode.hasFocus;
    return GestureDetector(
      onTap: () {
        if (hasFocus) {
          focusNode.unfocus();
        } else {
          focusNode.requestFocus();
        }
      },
      child: Container(
        decoration: BoxDecoration(
          color: hasFocus ? Colors.white : Color(0xFFF4F4F4),
          border: hasFocus
              ? Border.all(color: Color(0xFF0E4DA4), width: 2)
              : Border.all(width: 2, color: Colors.transparent),
          borderRadius: const BorderRadius.all(Radius.circular(5)),
          boxShadow: hasFocus
              ? [
                  BoxShadow(
                    color: Color(0xFFF4F4F4),
                    spreadRadius: 3,
                    blurRadius: 0,
                    offset: Offset(0, 0), // changes position of shadow
                  ),
                ]
              : [],
        ),
        child: TextFormField(
          enabled: enabled,
          key: this.customKey,
          controller: textEditingController,
          initialValue: initialValue,
          inputFormatters: isNumericalOnly
              ? [
                  FilteringTextInputFormatter.digitsOnly,
                  FilteringTextInputFormatter.singleLineFormatter,
                ]
              : [
                  FilteringTextInputFormatter.singleLineFormatter,
                ],
          keyboardType: isNumericalOnly ? TextInputType.number : TextInputType.text,
          focusNode: focusNodeToggle,
          maxLength: maxLength,
          validator: (String? value) {
            return validator != null ? validator!(value.toString()) : null;
          },
          onSaved: (String? value) {
            return onSaved != null ? onSaved!(value.toString()) : null;
          },
          onChanged: (String? value) {
            return onChanged != null ? onChanged!(value.toString()) : null;
          },
          buildCounter: maxLength != null && isCounterVisible == true
              ? (BuildContext context, {int? currentLength, int? maxLength, bool? isFocused}) =>
                  Container(child: Text('$currentLength/$maxLength'))
              : (BuildContext context, {int? currentLength, int? maxLength, bool? isFocused}) =>
                  null,
          decoration: InputDecoration(
            floatingLabelBehavior: FloatingLabelBehavior.auto,
            hintText: customHintText,
            helperText: customHelperText,
            helperMaxLines: 2,
            filled: true,
            fillColor: Colors.transparent,
            border: InputBorder.none,
            focusedBorder: InputBorder.none,
            enabledBorder: InputBorder.none,
            errorBorder: InputBorder.none,
            disabledBorder: InputBorder.none,
            labelStyle: hasFocus ? inputTheme.labelStyle : TextStyle(color: Color(0xFF525252)),
            label: Text.rich(
              TextSpan(
                children: <InlineSpan>[
                  WidgetSpan(
                    child: Text(
                      label.toString(),
                    ),
                  ),
                  WidgetSpan(
                      child: isDataloading
                          ? LoadingIndicator(
                              width: 15,
                              height: 15,
                            )
                          : Text('')),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }),
);

} }

First you need to 1 String for each field首先,每个字段需要 1 个字符串

String nameError = '';

Now you need to create validation function for this field like现在您需要为此字段创建验证函数,例如

void invalidName() {
    nameError = "Enter name";
  }

Now you need to create function where you can check all validation现在您需要创建可以检查所有验证的函数

    bool validateInput() {
        try {
          if (email.isNotEmpty) {
            return true;
          } else {
            if (nameController.text.isEmpty) { // Here check your controller value
              invalidName(); // here define validation error
              ...
              ...
            }
            return false;
          }
        } catch (e) {
          return false;
        }
      }

Now you just need to call validateInput() function in your button if its return true then call you api or something other wise shows error in below of textfield like below现在你只需要在你的按钮中调用 validateInput() 函数,如果它返回 true 然后调用你 api 或其他方式在文本字段下方显示错误,如下所示

nameError == '' ? SizedBox() : Text(nameError)

You can do this by maintaining a column of a TextFormField and Text Widget(for showing error message).您可以通过维护一列 TextFormField 和 Text Widget(用于显示错误消息)来做到这一点。 You can do something like this.你可以做这样的事情。

final FocusNode focusNode = Focus.of(context);
final bool hasFocus = focusNode.hasFocus;

Column(
  children: [
    Container(
      margin: EdgeInsets.symmetric(horizontal: 20.0),
      child: TextFormField(
        focusNode: focusNode,
        onFieldSubmitted: (v) {
          FocusScope.of(context).requestFocus(focus);
        },
        textInputAction: TextInputAction.next,
        controller: , //your controller
        autofocus: false,
        decoration: InputDecoration(
          hintText: "sample text*",
          errorStyle: TextStyle(color: Colors.red),
          hintStyle: TextStyle(
              fontSize: 20,
              color: Colors.grey),
          border: OutlineInputBorder(
            borderRadius:
                BorderRadius.circular(5),
            borderSide: BorderSide(
                //color: Colors.amber,
                ),
          ),
          enabledBorder: OutlineInputBorder(
            borderRadius:
                BorderRadius.circular(5),
            borderSide:
                BorderSide(width: 1, color: Colors.black),
          ),
        ),
        style: TextStyle(
          fontSize: 20,
          color: Colors.black,
        ),
      ),
    ),
    SizedBox(
      height: 5,
    ),
    Visibility(
        visible: hasFocus,
        child: Text(
          'Required field, it cannot be empty',
          style: TextStyle(color: Color.red),
        )),
  ],
);

You can remove wrapped container and style your text form as your container.您可以删除包装容器并将您的文本表单设置为您的容器。 In this way the error message will be displayed outside the grey area box.这样,错误消息将显示在灰色区域框之外。

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

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