Flutter 单击TextFormField会导致重建,文本字段随后会失去焦点
我的Flitter应用程序一直运行良好,直到昨天,我的登录屏幕开始出现奇怪的行为。只要我点击键盘上显示的用户名或密码文本字段,就会立即隐藏,然后一切都会重建。我在网上看到过一些关于类似问题的帖子,但没有任何东西能帮助我找出这里出了什么问题。这是守则的要点:Flutter 单击TextFormField会导致重建,文本字段随后会失去焦点,flutter,flutter-layout,Flutter,Flutter Layout,我的Flitter应用程序一直运行良好,直到昨天,我的登录屏幕开始出现奇怪的行为。只要我点击键盘上显示的用户名或密码文本字段,就会立即隐藏,然后一切都会重建。我在网上看到过一些关于类似问题的帖子,但没有任何东西能帮助我找出这里出了什么问题。这是守则的要点: static final _formKey = GlobalKey<FormState>(); TextEditingController _emailController = TextEditingController(
static final _formKey = GlobalKey<FormState>();
TextEditingController _emailController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(body: SingleChildScrollView(child: _buildBody()));
}
Widget _buildBody() {
return BlocProvider(create: (context) {
_loginBloc = LoginBloc(auth);
return _loginBloc;
}, child: BlocBuilder<LoginBloc, LoginState>(builder: (context, state) {
if (state is LoginFailure) {
_onWidgetDidBuild(() {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('${state.error}'),
backgroundColor: Colors.red,
),
);
});
_showErrorMessage(state.error);
}
return Container(
height: Styles().height(),
child: LoadingOverlay(
color: Colors.black,
opacity: 0.5,
isLoading: (state is LoginLoading),
progressIndicator: SpinKitThreeBounce(color: Colors.white),
child: Container(
padding: EdgeInsets.fromLTRB(30, 50, 30, 0),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [AppColors.DARK_BLUE, AppColors.GREEN])),
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(0, 0, 0, 50),
child: _showLogo()),
Card(
color: Colors.white,
elevation: 5,
child: Padding(
padding: EdgeInsets.all(10),
child: Form(
key: _formKey,
child: ListView(
shrinkWrap: true,
children: <Widget>[
_buildEmailInput(),
_buildPasswordInput(),
Padding(
padding: EdgeInsets.only(top: 20),
child: ButtonTheme(
height: 50,
child: FlatButton(
color: AppColors.MEDIUM_GREEN,
child: Text(
_formMode == FormMode.LOGIN
? 'Sign in with Email'
: 'Create Account',
style: TextStyle(
color: Colors.white,
fontSize: 15,
fontWeight:
FontWeight.bold)),
onPressed: _validateAndSubmit,
))),
_showSecondaryButton(),
Align(
alignment: Alignment.center,
child: GestureDetector(
onTap: _showLoginRecoveryModal,
child: Text(
'Forgot Password?',
style: TextStyle(
color: AppColors.LIGHT_BLUE,
fontSize: 15,
fontWeight: FontWeight.bold),
))),
],
),
))),
Padding(
padding: const EdgeInsets.only(top: 20.0, bottom: 20.0),
child: Align(
alignment: Alignment.center,
child: Text(
'OR',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
)),
),
_buildGoogleButton()
]))));
}));
}
Widget _buildEmailInput() {
return Padding(
padding: const EdgeInsets.only(top: 20),
child: TextFormField(
maxLines: 1,
controller: _emailController,
keyboardType: TextInputType.emailAddress,
autofocus: false,
decoration: InputDecoration(
hintText: 'Email',
icon: Icon(
Icons.mail,
color: Colors.grey,
)),
validator: (value) => !EmailEditingRegexValidator().isValid(value)
? 'Invalid email address'
: null,
onSaved: (value) {
if (StringUtils.isNotNullOrEmpty(value)) {
_email = value.trim();
} else {
_email = null;
}
},
),
);
}
Widget _buildPasswordInput() {
return Padding(
padding: const EdgeInsets.fromLTRB(0.0, 15.0, 0.0, 0.0),
child: TextFormField(
maxLines: 1,
controller: _passwordController,
obscureText: _hidePassword,
autofocus: false,
decoration: InputDecoration(
hintText: 'Password',
icon: Icon(
Icons.lock,
color: Colors.grey,
),
suffix: GestureDetector(
onTap: _toggleShowPassword,
child: Icon(
AntIcons.eye,
color: Colors.grey,
))),
validator: (value) => !NonEmptyStringValidator().isValid(value)
? 'Password can\'t be empty'
: null,
onSaved: (value) {
if (StringUtils.isNotNullOrEmpty(value)) {
_password = value.trim();
} else {
_password = null;
}
},
),
);
}
static final_formKey=GlobalKey();
TextEditingController_emailController=TextEditingController();
TextEditingController_passwordController=TextEditingController();
@凌驾
小部件构建(构建上下文){
返回脚手架(主体:SingleChildScrollView(子:_buildBody());
}
小部件_buildBody(){
返回BlocProvider(创建:(上下文){
_loginBloc=loginBloc(auth);
返回_loginBloc;
},子:BlocBuilder(生成器:(上下文,状态){
如果(状态为登录失败){
_onWidgetDidBuild(){
Scaffold.of(上下文).showSnackBar(
小吃条(
内容:文本(“${state.error}”),
背景颜色:Colors.red,
),
);
});
_错误消息(state.error);
}
返回容器(
高度:样式().height(),
孩子:把东西装上(
颜色:颜色,黑色,
不透明度:0.5,
isLoading:(状态为LoginLoading),
progressIndicator:SpinKitThreeBounce(颜色:Colors.white),
子:容器(
填充:从LTRB(30,50,30,0)开始的边缘设置,
装饰:盒子装饰(
梯度:线性梯度(
开始:Alignment.topCenter,
结束:对齐。底部中心,
颜色:[AppColors.深蓝,AppColors.GREEN]),
子项:列(子项:[
填充物(
填充:从LTRB(0,0,0,50)开始的边缘设置,
子项:_showLogo()),
卡片(
颜色:颜色,白色,
标高:5,
孩子:填充(
填充:边缘设置。全部(10),
孩子:表格(
键:_formKey,
子:ListView(
收缩膜:对,
儿童:[
_buildEmailInput(),
_buildPasswordInput(),
填充物(
填充:仅限边缘设置(顶部:20),
孩子:ButtonTheme(
身高:50,
孩子:扁平按钮(
颜色:AppColors.MEDIUM_绿色,
子:文本(
_formMode==formMode.LOGIN
?“使用电子邮件登录”
:“创建帐户”,
样式:TextStyle(
颜色:颜色,白色,
尺寸:15,
容重:
FontWeight.bold),
按下时:_validateAndSubmit,
))),
_ShowSecondary按钮(),
对齐(
对齐:对齐.center,
儿童:手势检测器(
onTap:_showLoginRecoveryModal,
子:文本(
“忘记密码了吗?”,
样式:TextStyle(
颜色:AppColors.LIGHT_蓝色,
尺寸:15,
fontWeight:fontWeight.bold),
))),
],
),
))),
填充物(
填充:仅限常量边集(顶部:20.0,底部:20.0),
子对象:对齐(
对齐:对齐.center,
子:文本(
或",,
样式:TextStyle(
颜色:颜色,白色,
尺寸:20,
fontWeight:fontWeight.bold),
)),
),
_buildGoogleButton()
]))));
}));
}
小部件_buildEmailInput(){
返回填充(
填充:仅限常量边集(顶部:20),
子项:TextFormField(
maxLines:1,
控制器:\u电子邮件控制器,
键盘类型:TextInputType.emailAddress,
自动对焦:错误,
装饰:输入装饰(
hintText:“电子邮件”,
图标:图标(
Icons.mail,
颜色:颜色。灰色,
)),
验证器:(值)=>!EmailEditingRegexValidator().isValid(值)
?“无效的电子邮件地址”
:null,
已保存:(值){
if(StringUtils.isNotNullOrEmpty(值)){
_email=value.trim();
}否则{
_电子邮件=空;
}
},
),