如何在 flutter 中使用验证器创建可重用的文本字段

how to create resuable textfield with validator in flutter

我正在创建一个包含用户名和密码字段的登录表单,我想在用户跳过任何字段时添加验证。我创建了这个可重复使用的文本字段。

class RoundedInputField extends StatelessWidget {
  final String hintText;
  final ValueChanged<String> onChanged;
  final TextEditingController controller;
  final FormFieldValidator validate;
  const RoundedInputField({Key key, this.hintText,
    this.onChanged,
   this.controller,this.validate,
 
  })
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return TextFieldContainer(
      child: TextFormField(
        onChanged: onChanged,            
        controller: TextEditingController(),
        validator: validate,
        decoration: InputDecoration(
          hintText: hintText,
          border: InputBorder.none,
        ),
      ),
    );
  }
}

并这样称呼它

 RoundedInputField(hintText: "Username",icon: Icons.email,fontsize: 20,
                controller: TextEditingController(text: user.username),
                onChanged: (value){
                  user.username=value;
                },
                validate: (value){
                  if(value.isEmpty){
                    return "This field is required";
                  }
                },
                ),

但是验证器 属性 没有正常工作,在这里。

如果有人知道如何修复它,请帮忙!

替换您的代码并试试这个:

RoundedInputField(
              hintText: "Username",
              icon: Icons.email,
              fontsize: 20,
              controller: TextEditingController(text: user.username),
              onChanged: (value) {
                user.username = value;
              },
              validate: (value) {
                if (value.isEmpty) {
                  return "This field is required";
                }
                return null;
              },
            ),

我一直在以这种可重用的方式使用 TextFormField,它满足了我需要的所有目的,我认为它也适用于你的情况

class BoxTextField extends StatelessWidget {
  final TextEditingController controller;
  final FormFieldValidator<String> validator;
  final bool obsecure;
  final bool readOnly;
  final VoidCallback onTap;
  final VoidCallback onEditingCompleted;
  final TextInputType keyboardType;
  final ValueChanged<String> onChanged;
  final bool isMulti;
  final bool autofocus;
  final bool enabled;
  final String errorText;
  final String label;
  final Widget suffix;
  final Widget prefix;

  BoxTextField(
      {Key key,
      this.controller,
      this.validator,
      this.keyboardType = TextInputType.text,
      this.obsecure = false,
      this.onTap,
      this.isMulti = false,
      this.readOnly = false,
      this.autofocus = false,
      this.errorText,
      @required this.label,
      this.suffix,
      this.prefix,
      this.enabled = true,
      this.onEditingCompleted,
      this.onChanged})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(vertical: 4),
      child: TextFormField(
          onChanged: onChanged,
          onEditingComplete: onEditingCompleted,
          autofocus: autofocus,
          minLines: isMulti ? 4 : 1,
          maxLines: isMulti ? null : 1,
          onTap: onTap,
          enabled: enabled,
          readOnly: readOnly,
          obscureText: obsecure,
          keyboardType: keyboardType,
          controller: controller,
          decoration: InputDecoration(
            errorText: errorText,
            prefixIcon: prefix,
            suffixIcon: suffix,
            labelStyle: TextStyle(fontSize: lableFontSize()),
            labelText: label,
            hintStyle: TextStyle(color: Colors.blueGrey, fontSize: 15),
            contentPadding: EdgeInsets.symmetric(vertical: 8, horizontal: 20),
            enabledBorder: textFieldfocused(),
            border: textFieldfocused(),
            focusedBorder: textFieldfocused(),
            errorBorder: errorrTextFieldBorder(),
            focusedErrorBorder: errorrTextFieldBorder(),
          ),
          validator: validator),
    );
  }
}

这是用法

class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  TextEditingController _emailPhone = new TextEditingController();
  TextEditingController _password = new TextEditingController();

  GlobalKey<FormState> _formKey = new GlobalKey<FormState>();

  @override
  void initState() {
    super.initState();
  }

  String loginError;
  bool loggingIn = false;

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        SliverList(
            delegate: SliverChildListDelegate([
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20.0),
            child: Form(
                key: _formKey,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    SizedBox(
                      height: 50,
                    ),
                    BoxTextField(
                      validator: (str) {
                        if (str.isEmpty) {
                          return tr('common.required');
                        }

                        return null;
                      },
                      controller: _emailPhone,
                      label: tr('login.username'),
                    ),
                    SizedBox(
                      height: 10,
                    ),
                    BoxTextField(
                      label: tr('login.password'),
                      controller: _password,
                      obsecure: true,
                      validator: (str) {
                        if (str.isEmpty) {
                          return tr('common.required');
                        }

                        return null;
                      },
                    ),
         Center(
                        child: BoxButton(
                      loading: loggingIn,
                      lable: tr('login.btn'),
                      onPressed: () {
                          
                            },
                    )),
                  ],
                )),
          )
        ]))
      ],
    );
  }
}