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

问题描述

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

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";
                  }
                },

但验证器属性无法正常工作,就在这里

enter image description here

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

解决方法

替换您的代码并尝试此操作:

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: () {
                          
                            },)),],)
        ]))
      ],);
  }
}