在 Flutter 中,我正在尝试基于文本控制器动态更新我的列小部件。我该怎么做呢?
In Flutter, I'm trying to dynamically update my column widget based on Text Controller. How do I do this?
我想要实现的是仅在未验证文本控制器时显示一条消息,否则显示一个空容器。如何根据文本控制器输出的内容重新绘制小部件?
想要的行为:
- 当用户点击登录按钮时,flutter 检查用户名字段是否为空。
- 如果为空,则在登录按钮下方显示消息。
- 当用户再次单击文本字段并键入一个字符时,消息就会消失,并且 returns 一个空容器。
代码:
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: TextFieldExample(),
),
),
);
}
}
class TextFieldExample extends StatefulWidget {
@override
_TextFieldExampleState createState() => _TextFieldExampleState();
}
class _TextFieldExampleState extends State<TextFieldExample> {
@override
void initState() {
super.initState();
_username.addListener(() {
setState(() {});
});
}
final _username = TextEditingController();
bool hasMessage = false;
String email = '';
String validatorMessage;
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 5),
padding: EdgeInsets.symmetric(horizontal: 15),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(29)),
child: Column(children: <Widget>[
TextField(
controller: _username,
decoration:
InputDecoration(icon: Icon(Icons.person), hintText: "Email"),
),
Container(
margin: EdgeInsets.symmetric(vertical: 5),
child: ClipRRect(
borderRadius: BorderRadius.circular(29),
child: RaisedButton(
padding: EdgeInsets.symmetric(vertical: 10),
onPressed: () async {
if (_username.text.isNotEmpty) {
//do sign in
} else {
hasMessage = true;
validatorMessage = 'Check username or password';
}
},
child: Text("Login")))),
//Change something here, in order to dynamically check and update
if (hasMessage == false)
Container()
else
Container(
alignment: Alignment.center,
child:
Text(validatorMessage, style: TextStyle(color: Colors.red))),
]),
);
}
}
要动态更改显示文本的小部件,您需要使用 StreamBuilder,它会为每个新事件重建:
String validatorMessage;
bool validate = false; //will be true if the user clicked in the login button
final _usernameController = StreamController<String>(); //stream to validate the text
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.symmetric(vertical: 5),
padding: EdgeInsets.symmetric(horizontal: 15),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(29),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
onChanged: _usernameController.add, //everytime the text changes a new value will be added to the stream
decoration: InputDecoration(
icon: Icon(Icons.person),
hintText: "Email",
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 5),
child: ClipRRect(
borderRadius: BorderRadius.circular(29),
child: RaisedButton(
padding: EdgeInsets.symmetric(vertical: 10),
onPressed: () {
setState(() {
validate = true;
});
},
child: Text("Login"),
),
),
),
StreamBuilder<String>(
initialData: '',
stream: _usernameController.stream,
builder: (context, snapshot) {
if (snapshot.data.isEmpty && validate == true) { //checking the stream and if the user clicked in the button
return Container(
alignment: Alignment.center,
child: Text(
'Check your e-mail and password.',
style: TextStyle(
color: Colors.red,
),
),
);
} else {
return Container();
}
},
),
],
),
),
);
}
@override
void dispose() {
_usernameController.close();
super.dispose();
}
我想要实现的是仅在未验证文本控制器时显示一条消息,否则显示一个空容器。如何根据文本控制器输出的内容重新绘制小部件?
- 当用户点击登录按钮时,flutter 检查用户名字段是否为空。
- 如果为空,则在登录按钮下方显示消息。
- 当用户再次单击文本字段并键入一个字符时,消息就会消失,并且 returns 一个空容器。
代码:
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: TextFieldExample(),
),
),
);
}
}
class TextFieldExample extends StatefulWidget {
@override
_TextFieldExampleState createState() => _TextFieldExampleState();
}
class _TextFieldExampleState extends State<TextFieldExample> {
@override
void initState() {
super.initState();
_username.addListener(() {
setState(() {});
});
}
final _username = TextEditingController();
bool hasMessage = false;
String email = '';
String validatorMessage;
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(vertical: 5),
padding: EdgeInsets.symmetric(horizontal: 15),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(29)),
child: Column(children: <Widget>[
TextField(
controller: _username,
decoration:
InputDecoration(icon: Icon(Icons.person), hintText: "Email"),
),
Container(
margin: EdgeInsets.symmetric(vertical: 5),
child: ClipRRect(
borderRadius: BorderRadius.circular(29),
child: RaisedButton(
padding: EdgeInsets.symmetric(vertical: 10),
onPressed: () async {
if (_username.text.isNotEmpty) {
//do sign in
} else {
hasMessage = true;
validatorMessage = 'Check username or password';
}
},
child: Text("Login")))),
//Change something here, in order to dynamically check and update
if (hasMessage == false)
Container()
else
Container(
alignment: Alignment.center,
child:
Text(validatorMessage, style: TextStyle(color: Colors.red))),
]),
);
}
}
要动态更改显示文本的小部件,您需要使用 StreamBuilder,它会为每个新事件重建:
String validatorMessage;
bool validate = false; //will be true if the user clicked in the login button
final _usernameController = StreamController<String>(); //stream to validate the text
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.symmetric(vertical: 5),
padding: EdgeInsets.symmetric(horizontal: 15),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(29),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
onChanged: _usernameController.add, //everytime the text changes a new value will be added to the stream
decoration: InputDecoration(
icon: Icon(Icons.person),
hintText: "Email",
),
),
Container(
margin: EdgeInsets.symmetric(vertical: 5),
child: ClipRRect(
borderRadius: BorderRadius.circular(29),
child: RaisedButton(
padding: EdgeInsets.symmetric(vertical: 10),
onPressed: () {
setState(() {
validate = true;
});
},
child: Text("Login"),
),
),
),
StreamBuilder<String>(
initialData: '',
stream: _usernameController.stream,
builder: (context, snapshot) {
if (snapshot.data.isEmpty && validate == true) { //checking the stream and if the user clicked in the button
return Container(
alignment: Alignment.center,
child: Text(
'Check your e-mail and password.',
style: TextStyle(
color: Colors.red,
),
),
);
} else {
return Container();
}
},
),
],
),
),
);
}
@override
void dispose() {
_usernameController.close();
super.dispose();
}