在 flutter 中从文本字段获取价值的问题
Issue in getting value from textfield in flutter
我是 Flutter 新手。
我正在尝试放置 2 个文本字段,即电子邮件和密码。
和一个登录按钮。
如果用户单击登录按钮,我想检查文本字段中的值。如果是 "username and password = admin",我想打印一条消息 "Login successful"。
为了获取文本字段中的值,我使用 controller 来获取文本。但是如果我在 切换到下一个文本字段时使用控制器,则第一个中的值会自动删除 。我不知道是什么问题。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'stacked_icons.dart';
import 'main.dart';
class LoginPage extends StatelessWidget {
final emailController = TextEditingController();
final passwordController = TextEditingController();
@override
Widget build(BuildContext context) { SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark.copyWith(
statusBarColor: Colors.orange, //or set color with: Color(0xFF0000FF)
));
return new Scaffold(
appBar: new AppBar(
backgroundColor:Colors.transparent,
elevation: 0.0,
iconTheme: new IconThemeData(color: Color(0xFF18D191))),
body: Container(
width: double.infinity,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new StakedIcons(),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8.0, bottom: 80.0),
child: new Text(
"Village",
style: new TextStyle(fontSize: 30.0),
),
)
],
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0),
child: TextField(
controller: emailController,
decoration:
new InputDecoration(labelText: 'Email'),
),
),
new SizedBox(
height: 15.0,
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0),
child: TextField(
obscureText: true,
decoration: InputDecoration(labelText: 'Password'),
//controller: passwordController
),
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 5.0, top: 10.0),
child: GestureDetector(
onTap: () {
debugPrint(passwordController.text+emailController.text);
},
child: new Container(
alignment: Alignment.center,
height: 60.0,
decoration: new BoxDecoration(
color: Color(0xFF18D191),
borderRadius: new BorderRadius.circular(9.0)),
child: new Text("Login",
style: new TextStyle(
fontSize: 20.0, color: Colors.white))),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 20.0, top: 10.0),
child: new Container(
alignment: Alignment.center,
height: 60.0,
child: new Text("Forgot Password?",
style: new TextStyle(
fontSize: 17.0, color: Color(0xFF18D191)))),
),
)
],
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom:18.0),
child: new Text("Create A New Account ",style: new TextStyle(
fontSize: 17.0, color: Color(0xFF18D191),fontWeight: FontWeight.bold)),
),
],
),
)
],
),
),
);}}
如果我删除控制器,文本字段中的值将起作用。但是如果不使用控制器,我不知道如何获取文本。
您应该将 email
和 password
字段包装到 Form
小部件中,并将它们的类型更改为 TextFormField
以提供 validator
函数,以便按下按钮时可以调用它:
final _formKey = GlobalKey<FormState>();
Form(
key: _formKey,
child: Column(
children: <widget>[
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0),
child: TextFormField(
controller: emailController,
decoration:
new InputDecoration(labelText: 'Email'),
validator: //Your validator function here
),
),
new SizedBox(
height: 15.0,
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0),
child: TextFormField(
obscureText: true,
decoration: InputDecoration(labelText: 'Password'),
//controller: passwordController,
validator: //Your validator function here
),
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 5.0, top: 10.0),
child: GestureDetector(
onTap: () {
debugPrint(passwordController.text+emailController.text);
if(_formKey.currentState.validate()){
//This will only be reached if there both fields has valid input
}
},
child: new Container(
alignment: Alignment.center,
height: 60.0,
decoration: new BoxDecoration(
color: Color(0xFF18D191),
borderRadius: new BorderRadius.circular(9.0)),
child: new Text("Login",
style: new TextStyle(
fontSize: 20.0, color: Colors.white))),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 20.0, top: 10.0),
child: new Container(
alignment: Alignment.center,
height: 60.0,
child: new Text("Forgot Password?",
style: new TextStyle(
fontSize: 17.0, color: Color(0xFF18D191)))),
),
)
],
),
]
),
),
这是电子邮件字段的 validator
函数示例:
validator: (val) => val.isEmpty ? 'Email is required' : null
val
是字段中的当前文本,因此当结果为 null
时,表单将知道 val
是有效输入,否则不会提交。
听起来您正在寻找 TextField
https://docs.flutter.io/flutter/material/TextField/TextField.html
的 onChanged
参数
TextField('foo', onChanged((s) => setState(() => myText = s)))
您使用的是无状态小部件,这意味着每次 UI 更改时都会创建一个全新的实例,例如当您切换到下一个字段时。这包括您的控制器 - 当您将焦点从一个字段更改到另一个字段时,它们会重新初始化,这就是它们重置为空白值的原因。
您需要使用有状态小部件,并在 build()
方法之外初始化控制器。这样,当 UI 更改时,它会被重建,但小部件的状态(包括您的控制器及其值)会保留。
如果您使用的是 Android Studio,您只需单击此行的任意位置 class LoginPage extends StatelessWidget {
,然后按 Alt+Enter,然后单击 "Convert to StatefulWidget"。 VSCode 中也有它的快捷方式,但我不知道。
我是 Flutter 新手。 我正在尝试放置 2 个文本字段,即电子邮件和密码。 和一个登录按钮。 如果用户单击登录按钮,我想检查文本字段中的值。如果是 "username and password = admin",我想打印一条消息 "Login successful"。 为了获取文本字段中的值,我使用 controller 来获取文本。但是如果我在 切换到下一个文本字段时使用控制器,则第一个中的值会自动删除 。我不知道是什么问题。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'stacked_icons.dart';
import 'main.dart';
class LoginPage extends StatelessWidget {
final emailController = TextEditingController();
final passwordController = TextEditingController();
@override
Widget build(BuildContext context) { SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark.copyWith(
statusBarColor: Colors.orange, //or set color with: Color(0xFF0000FF)
));
return new Scaffold(
appBar: new AppBar(
backgroundColor:Colors.transparent,
elevation: 0.0,
iconTheme: new IconThemeData(color: Color(0xFF18D191))),
body: Container(
width: double.infinity,
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new StakedIcons(),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8.0, bottom: 80.0),
child: new Text(
"Village",
style: new TextStyle(fontSize: 30.0),
),
)
],
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0),
child: TextField(
controller: emailController,
decoration:
new InputDecoration(labelText: 'Email'),
),
),
new SizedBox(
height: 15.0,
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0),
child: TextField(
obscureText: true,
decoration: InputDecoration(labelText: 'Password'),
//controller: passwordController
),
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 5.0, top: 10.0),
child: GestureDetector(
onTap: () {
debugPrint(passwordController.text+emailController.text);
},
child: new Container(
alignment: Alignment.center,
height: 60.0,
decoration: new BoxDecoration(
color: Color(0xFF18D191),
borderRadius: new BorderRadius.circular(9.0)),
child: new Text("Login",
style: new TextStyle(
fontSize: 20.0, color: Colors.white))),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 20.0, top: 10.0),
child: new Container(
alignment: Alignment.center,
height: 60.0,
child: new Text("Forgot Password?",
style: new TextStyle(
fontSize: 17.0, color: Color(0xFF18D191)))),
),
)
],
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom:18.0),
child: new Text("Create A New Account ",style: new TextStyle(
fontSize: 17.0, color: Color(0xFF18D191),fontWeight: FontWeight.bold)),
),
],
),
)
],
),
),
);}}
如果我删除控制器,文本字段中的值将起作用。但是如果不使用控制器,我不知道如何获取文本。
您应该将 email
和 password
字段包装到 Form
小部件中,并将它们的类型更改为 TextFormField
以提供 validator
函数,以便按下按钮时可以调用它:
final _formKey = GlobalKey<FormState>();
Form(
key: _formKey,
child: Column(
children: <widget>[
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0),
child: TextFormField(
controller: emailController,
decoration:
new InputDecoration(labelText: 'Email'),
validator: //Your validator function here
),
),
new SizedBox(
height: 15.0,
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 20.0, vertical: 0.0),
child: TextFormField(
obscureText: true,
decoration: InputDecoration(labelText: 'Password'),
//controller: passwordController,
validator: //Your validator function here
),
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 5.0, top: 10.0),
child: GestureDetector(
onTap: () {
debugPrint(passwordController.text+emailController.text);
if(_formKey.currentState.validate()){
//This will only be reached if there both fields has valid input
}
},
child: new Container(
alignment: Alignment.center,
height: 60.0,
decoration: new BoxDecoration(
color: Color(0xFF18D191),
borderRadius: new BorderRadius.circular(9.0)),
child: new Text("Login",
style: new TextStyle(
fontSize: 20.0, color: Colors.white))),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 10.0, right: 20.0, top: 10.0),
child: new Container(
alignment: Alignment.center,
height: 60.0,
child: new Text("Forgot Password?",
style: new TextStyle(
fontSize: 17.0, color: Color(0xFF18D191)))),
),
)
],
),
]
),
),
这是电子邮件字段的 validator
函数示例:
validator: (val) => val.isEmpty ? 'Email is required' : null
val
是字段中的当前文本,因此当结果为 null
时,表单将知道 val
是有效输入,否则不会提交。
听起来您正在寻找 TextField
https://docs.flutter.io/flutter/material/TextField/TextField.html
onChanged
参数
TextField('foo', onChanged((s) => setState(() => myText = s)))
您使用的是无状态小部件,这意味着每次 UI 更改时都会创建一个全新的实例,例如当您切换到下一个字段时。这包括您的控制器 - 当您将焦点从一个字段更改到另一个字段时,它们会重新初始化,这就是它们重置为空白值的原因。
您需要使用有状态小部件,并在 build()
方法之外初始化控制器。这样,当 UI 更改时,它会被重建,但小部件的状态(包括您的控制器及其值)会保留。
如果您使用的是 Android Studio,您只需单击此行的任意位置 class LoginPage extends StatelessWidget {
,然后按 Alt+Enter,然后单击 "Convert to StatefulWidget"。 VSCode 中也有它的快捷方式,但我不知道。