Flutter:TextFormField Validator 打破了字段的样式

Posted

技术标签:

【中文标题】Flutter:TextFormField Validator 打破了字段的样式【英文标题】:Flutter: TextFormField Validator breaks the style of field 【发布时间】:2020-04-08 17:09:00 【问题描述】:

    我有这个 TextFormField,我正在努力实现登录/注册屏幕。问题是当验证器将错误弹出到屏幕上时,TextFormField 的边框从圆形边缘变为方形。我该怎么做才能打印出错误?我正在考虑打印整个表单上方或下方的所有内容,但是使用 Valdiator 属性的方法呢? 还是有更有效的方法?

    TextFormField 所在的 ListView 似乎在此过程中被破坏,使得在屏幕上打印出验证器后键入非常烦人。

beforeValidator afterValidator

只是 TextFormField:

TextFormField(
                  validator: (String str) =>
                      str.isEmpty ? 'Enter a username' : null,
                  decoration: InputDecoration(
                    hintText: 'theChadMaster76',
                    hintStyle: TextStyle(
                      fontStyle: FontStyle.italic,
                    ),
                    enabledBorder: OutlineInputBorder(
                      borderSide: BorderSide(color: Colors.green),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    focusedBorder: OutlineInputBorder(
                      //focusBorder changes or not when user first clicks on the field
                      borderSide: BorderSide(color: Colors.blueAccent),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    prefixIcon: Icon(Icons
                        .account_circle), //make the icon also change its color
                    filled: true,
                    fillColor: Colors.grey.shade200,
                  ),
                  textAlign: TextAlign.center,
                  textAlignVertical: TextAlignVertical.bottom,
                  onChanged: (String str) 
                    setState(() 
                      userName = str;
                    );
                  ,
                ),

整个文件:

class RegistrationScreen extends StatefulWidget 
  static const String id = 'registration_screen';
  @override
  _RegistrationScreenState createState() => _RegistrationScreenState();


class _RegistrationScreenState extends State<RegistrationScreen> 
  final AuthService _auth = AuthService();
  final _formKey = GlobalKey<FormState>();
  bool loading = false;
  String error = '';

  String userName = "";
  String email = "";
  String password = "";
  @override
  Widget build(BuildContext context) 
    return loading ? Loading() : Scaffold(
      appBar: AppBarModel(),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 30.0),
        child: Center(
          child: Form(
            key: _formKey,
            child: ListView(
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 50.0),
                  child: Center(child: Text('add logo')),
                ),
                Padding(
                  padding: const EdgeInsets.only(left: 20.0, bottom: 10.0),
                  child: Text(
                    'Username:',
                    style: TextStyle(
                      fontSize: 18.0,
                      fontWeight: FontWeight.w600,
                      //fontStyle: FontStyle.italic,
                    ),
                  ),
                ),
                TextFormField(
                  validator: (String str) =>
                      str.isEmpty ? 'Enter a username' : null,
                  decoration: InputDecoration(
                    hintText: 'theChadMaster76',
                    hintStyle: TextStyle(
                      fontStyle: FontStyle.italic,
                    ),
                    enabledBorder: OutlineInputBorder(
                      borderSide: BorderSide(color: Colors.green),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    focusedBorder: OutlineInputBorder(

                      borderSide: BorderSide(color: Colors.blueAccent),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    prefixIcon: Icon(Icons
                        .account_circle), //make the icon also change its color
                    filled: true,
                    fillColor: Colors.grey.shade200,
                  ),
                  textAlign: TextAlign.center,
                  textAlignVertical: TextAlignVertical.bottom,
                  onChanged: (String str) 
                    setState(() 
                      userName = str;
                    );
                  ,
                ),
                SizedBox(height: 30.0),
                Padding(
                  padding: const EdgeInsets.only(left: 20.0, bottom: 10.0),
                  child: Text(
                    'Email:',
                    style: TextStyle(
                      fontSize: 18.0,
                      fontWeight: FontWeight.w600,
                      //fontStyle: FontStyle.italic,
                    ),
                  ),
                ),
                TextFormField(
                  keyboardType: TextInputType.emailAddress,
                  validator: (String str) =>
                      str.isEmpty ? 'Enter an email' : null,
                  decoration: InputDecoration(
                    hintText: 'bobbyBob@gmail.com',
                    hintStyle: TextStyle(
                      fontStyle: FontStyle.italic,
                    ),
                    enabledBorder: OutlineInputBorder(
                      borderSide: BorderSide(color: Colors.green),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    focusedBorder: OutlineInputBorder(

                      borderSide: BorderSide(color: Colors.blueAccent),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    prefixIcon:
                        Icon(Icons.mail),
                    filled: true,
                    fillColor: Colors.grey.shade200,
                  ),
                  textAlign: TextAlign.center,
                  textAlignVertical: TextAlignVertical.bottom,
                  onChanged: (String str) 
                    setState(() 
                      email = str;
                    );
                  ,
                ),
                SizedBox(height: 30.0),
                Padding(
                  padding: const EdgeInsets.only(left: 20.0, bottom: 10.0),
                  child: Text(
                    'Password:',
                    style: TextStyle(
                      fontSize: 18.0,
                      fontWeight: FontWeight.w600,
                      //fontStyle: FontStyle.italic,
                    ),
                  ),
                ),
                TextFormField(
                  validator: (String str) =>
                      str.length < 6 ? 'Enter an password 6+ char' : null,
                  obscureText: true,
                  decoration: InputDecoration(
                    hintText: 'secretPassword123!',
                    hintStyle: TextStyle(
                      fontStyle: FontStyle.italic,
                    ),
                    enabledBorder: OutlineInputBorder(
                      borderSide: BorderSide(color: Colors.green),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    focusedBorder: OutlineInputBorder(

                      borderSide: BorderSide(color: Colors.blueAccent),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    prefixIcon: Icon(Icons.memory),
                    filled: true,
                    fillColor: Colors.grey.shade200,
                  ),
                  textAlign: TextAlign.center,
                  textAlignVertical: TextAlignVertical.bottom,
                  onChanged: (String str) 
                    setState(() 
                      password = str;
                    );
                  ,
                ),
                SizedBox(
                  height: 50.0,
                ),
                Center(
                  child: FlatButton(
                    shape: RoundedRectangleBorder(
                      borderRadius: new BorderRadius.circular(30.0),
                      side: BorderSide(color: Colors.green.shade400),
                    ),
                    color: Colors.green.shade400,
                    textColor: Colors.grey.shade300,
                    padding:
                        EdgeInsets.symmetric(horizontal: 120.0, vertical: 10.0),
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(
                        'SUBMIT',
                        style: TextStyle(
                          fontSize: 18.0,
                          letterSpacing: 4.0,
                          fontStyle: FontStyle.italic,
                        ),
                      ),
                    ),
                    onPressed: () async 
                      if (_formKey.currentState.validate()) 
                        setState(() 
                          loading = true;
                        );
                        dynamic result = await _auth.registerWithEmailPassUser(
                            email, password);
                        if (result == null) 
                          setState(() 
                            loading = false;
                            error = "please supply a valid email";
                          );
                        
                      
                    ,
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  

【问题讨论】:

【参考方案1】:

您只需要覆盖errorBoder 样式,就像您为focusedBorder,enabledBorder 所做的那样。下面是代码sn-p。

errorBorder: OutlineInputBorder(

                      borderSide: BorderSide(color: Colors.red),
                      borderRadius: BorderRadius.circular(35.0),
                    )

你最终的 TextFormFiled 应该是这样的

TextFormField(
                  validator: (String str) =>
                      str.isEmpty ? 'Enter a username' : null,
                  decoration: InputDecoration(
                    hintText: 'theChadMaster76',
                    hintStyle: TextStyle(
                      fontStyle: FontStyle.italic,
                    ),
                    enabledBorder: OutlineInputBorder(
                      borderSide: BorderSide(color: Colors.green),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    focusedBorder: OutlineInputBorder(

                      borderSide: BorderSide(color: Colors.blueAccent),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    errorBorder: OutlineInputBorder(

                      borderSide: BorderSide(color: Colors.red),
                      borderRadius: BorderRadius.circular(35.0),
                    ),
                    prefixIcon: Icon(Icons
                        .account_circle), //make the icon also change its color
                    filled: true,
                    fillColor: Colors.grey.shade200,
                  ),
                  textAlign: TextAlign.center,
                  textAlignVertical: TextAlignVertical.bottom,
                  onChanged: (String str) 
                    setState(() 
                      userName = str;
                    );
                  ,
                )

【讨论】:

你可以在这里查看dartpad.dev/1dc24e6c5a38f6d0a914b3620ea0a20b 非常感谢。我还必须添加focusedErrorBorder,现在我明白为什么了。【参考方案2】:

您还必须指定 errorBorder 和focusedErrorBorder:

errorBorder: OutlineInputBorder(
   borderSide: BorderSide(color: Colors.red),
   borderRadius: BorderRadius.circular(35.0),
),
focusedErrorBorder: OutlineInputBorder(
   borderSide: BorderSide(color: Colors.red),
   borderRadius: BorderRadius.circular(35.0),
),

请参阅InputDecoration 了解所有可用选项。

【讨论】:

以上是关于Flutter:TextFormField Validator 打破了字段的样式的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 键盘隐藏时TextFormField变为空白

更改 FLUTTER 中 TextFormField 的默认边框颜色

Flutter 扩展/占用 TextFormField 以填充屏幕的其余部分

Flutter 2 - 设置自动完成 TextFormField 的初始值

在 TextFormField 中检测新行 - Flutter

TextFormField 输入文本溢出与 DropdownButtonFormField, Flutter