Flutter注册页面输入框空校验不生效及死代码问题如何解决
问题根因
你的代码存在3处核心错误,直接导致预期逻辑无法生效:
- 所有
TextEditingController、空值标记布尔变量、dispose生命周期方法都错误定义在build方法内部。build方法每次UI重绘都会重新执行,所有变量都会被重置为初始值,IDE判定三元表达式的判断分支为死代码正是因为这个原因——在单次build的作用域内,布尔变量永远是初始的false,不会变化。 - 点击注册按钮修改布尔标记后,没有调用
setState方法触发UI重绘,就算变量位置正确,错误提示也不会显示。 - 点击注册按钮没有加校验判断逻辑,不管输入是否符合要求,都会直接执行页面跳转。
修改后的完整代码
import 'package:club_mark_2/styles/style.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'userPreferences/user_details_preference.dart'; class RegisterScreen extends StatefulWidget { const RegisterScreen({Key? key}) : super(key: key); @override _RegisterScreenState createState() => _RegisterScreenState(); } class _RegisterScreenState extends State<RegisterScreen> { // 把控制器、状态变量移到build外部,作为State类的成员变量 final registerEmail = TextEditingController(); final registerPassword = TextEditingController(); final verifyPassword = TextEditingController(); final registerName = TextEditingController(); bool _emptyboxmail = false; bool _emptyboxpass = false; bool _emptyboxverify = false; bool _emptyboxregistername = false; // dispose生命周期方法放在类内部,build外部 @override void dispose() { registerEmail.dispose(); registerPassword.dispose(); verifyPassword.dispose(); registerName.dispose(); super.dispose(); } @override Widget build(BuildContext context) { double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; return Scaffold( backgroundColor: Colors.transparent, body: SizedBox( width: width, height: height, child: Stack(children: <Widget>[ Padding( padding: const EdgeInsets.only(left: 15, top: 165, right: 15), child: ListView( children: [ Center( child: Text( 'SIGN UP', style: TextStyle( color: Colors.white, fontSize: 30.0, fontWeight: FontWeight.bold, fontFamily: 'Montserrat', ), ), ), Container( padding: EdgeInsets.all(8.0), child: TextFormField( style: TextStyle(color: Colors.white), decoration: InputDecoration( errorText: _emptyboxregistername ? 'field cannot be empty' : null, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.grey.withOpacity(0.5)), borderRadius: BorderRadius.circular(20)), hintText: 'Full Name', hintStyle: TextStyle(color: kcMediumGreyColor), labelStyle: TextStyle(color: Colors.white), prefixIcon: const Icon( Icons.person, color: Colors.white, ), ), controller: registerName, ), ), SizedBox( height: 5, ), Container( padding: EdgeInsets.all(8.0), child: TextFormField( style: TextStyle(color: Colors.white), decoration: InputDecoration( errorText: _emptyboxmail ? 'field cannot be empty' : null, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.grey.withOpacity(0.5)), borderRadius: BorderRadius.circular(20), ), hintText: 'E-mail', hintStyle: TextStyle(color: kcMediumGreyColor), labelStyle: TextStyle(color: Colors.white), prefixIcon: const Icon( Icons.email, color: Colors.white, ), ), controller: registerEmail, ), ), SizedBox( height: 5, ), Container( padding: EdgeInsets.all(8.0), child: TextFormField( style: TextStyle(color: Colors.white), obscureText: true, decoration: InputDecoration( errorText: _emptyboxpass ? 'field cannot be empty' : null, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.grey.withOpacity(0.5)), borderRadius: BorderRadius.circular(20), ), hintText: 'Password', hintStyle: TextStyle(color: kcMediumGreyColor), labelStyle: TextStyle( color: Colors.white, ), prefixIcon: const Icon( Icons.lock, color: Colors.white, ), ), controller: registerPassword, ), ), SizedBox( height: 5, ), Container( padding: EdgeInsets.all(8.0), child: TextFormField( style: TextStyle(color: Colors.white), obscureText: true, decoration: InputDecoration( errorText: _emptyboxverify ? 'field cannot be empty' : null, enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Colors.grey.withOpacity(0.5)), borderRadius: BorderRadius.circular(20), ), hintText: 'Verify Password', hintStyle: TextStyle(color: kcMediumGreyColor), labelStyle: TextStyle(color: Colors.white), prefixIcon: const Icon( Icons.lock, color: Colors.white, ), ), controller: verifyPassword, ), ), SizedBox( height: 20, ), SizedBox( height: 60, child: TextButton( style: ButtonStyle( shape: MaterialStateProperty.all<RoundedRectangleBorder>( RoundedRectangleBorder( borderRadius: BorderRadius.circular(18.0), ), ), ), onPressed: () { // 修改状态后调用setState触发重绘 setState(() { _emptyboxmail = registerEmail.text.isEmpty; _emptyboxregistername = registerName.text.isEmpty; _emptyboxpass = registerPassword.text.isEmpty; _emptyboxverify = verifyPassword.text.isEmpty; }); // 加校验判断,所有输入都不为空才跳转 if(!_emptyboxmail && !_emptyboxregistername && !_emptyboxpass && !_emptyboxverify) { Navigator.push( context, MaterialPageRoute( builder: (context) => UserDetailsPreference(), ), ); } }, child: Text('Sign Up'), ), ), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: EdgeInsets.all(8.0), child: Text( "━━━━━ OR SIGN UP WITH ━━━━━", style: TextStyle(color: kcMediumGreyColor), ), ), ], ), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ InkWell( onTap: () {}, child: Container( decoration: BoxDecoration(), child: ClipRRect( borderRadius: BorderRadius.circular(10.0), child: Image.asset('lib/assets/images/googleIcon.png', width: 50.0, height: 50.0), ), ), ), SizedBox( width: 30, ), InkWell( onTap: () {}, child: Container( decoration: BoxDecoration(), child: ClipRRect( child: Image.asset( 'lib/assets/images/facebookIcon.png', width: 45.0, height: 45.0), ), ), ), ], ), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( padding: EdgeInsets.all(8.0), child: Text( "Already have an account?", style: TextStyle(color: Colors.white), ), ), Text( "SIGN IN", style: TextStyle(color: kcPrimaryColor), ), ], ), ], ), ), ]), ), ); } }
额外优化说明
你还可以给TextFormField加上onChanged回调,在用户输入内容后自动隐藏对应错误提示,使用体验更好:
onChanged: (val) { if(_emptyboxregistername && val.isNotEmpty) { setState(() => _emptyboxregistername = false); } }
内容的提问来源于stack exchange,提问作者Dimitris Konstantinou
相关产品推荐
相关产品推荐

