我已经实现了一个 TextField,它允许用户在我的 flutter 应用程序中输入。现在,我想在按下按钮时将用户输入数据保存到变量中,以便以后使用。在我看来,为了实现这一点,我必须创建有状态小部件及其状态的特定实例,以便当我调用小部件来提取变量时,它不会创建带有空文本字段。有问题的文本字段是 ProjectNameField 和 ProjectDescriptionField。 这是我的实现:
ProjectDescriptionField savedDescription = ProjectDescriptionField();
ProjectNameField savedName = ProjectNameField();
AddPage savedPage = AddPage();
_AddPageState savedPageState = _AddPageState();
List<String> image_list_encoded = [];
class AddPage extends StatefulWidget {
final _AddPageState _addPageState = _AddPageState();
AddPage({Key? key}) : super(key: key);
@override
_AddPageState createState() => _AddPageState();
}
class _AddPageState extends State<AddPage> {
List<Asset> images = <Asset>[];
String _error = NOERROR;
@override
Widget build(BuildContext context) {
if (images.isEmpty)
return AppLayout(logicalHeight * 0.15);
else
return AppLayout(logicalHeight * 0.01);
}
List<Asset> getImages() {
return images;
}
Widget AppLayout(double distanceFromImages) {
return Scaffold(
appBar: AppBar(
leading: BackButton(color: Colors.white),
title: Text(CREATEPROJECT),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.check,
color: Colors.white,
),
onPressed: () {
SavedData _savedData = SavedData(
savedName._nameFieldState.myController.value.text,
savedDescription
._descriptionFieldState.myController.value.text,
savedPage._addPageState.getImages());
print(_savedData.saved_Project_Description);
print(_savedData.saved_Project_Name);
print(_savedData.saved_images.toString());
saveNewProject(_savedData);
},
),
],
),
body: Column(children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.02, 0, 0),
child: Center(
child: Container(
height: logicalHeight * 0.05,
width: logicalWidth * 0.9,
child: savedName)),
),
Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.01, 0, 0),
child: ElevatedButton(
child: Text(PICKIMAGES),
onPressed: loadAssets,
)),
Center(
child: Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.01, 0, 0),
child: getWidget())),
Padding(
padding: EdgeInsets.fromLTRB(
logicalWidth * 0.05, distanceFromImages, logicalWidth * 0.05, 0),
child: Center(child: Container(child: savedDescription)),
),
]),
);
}
Widget getWidget() {
if (images.length > 0) {
return Container(
height: logicalHeight * 0.4,
width: logicalWidth * 0.8,
child: ImagePages());
} else {
return Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.15, 0, 0),
child: Container(child: Text(NOPICTURESSELECTED)));
}
}
PageView ImagePages() {
final PageController controller = PageController(initialPage: 0);
List<Widget> children = [];
images.forEach((element) {
children.add(Padding(
padding: EdgeInsets.fromLTRB(
logicalWidth * 0.01, 0, logicalWidth * 0.01, 0),
child: AssetThumb(
asset: element,
width: 1000,
height: 1000,
)));
});
return PageView(
scrollDirection: Axis.horizontal,
controller: controller,
children: children,
);
}
}
class ProjectNameField extends StatefulWidget {
ProjectNameFieldState _nameFieldState = ProjectNameFieldState();
@override
ProjectNameFieldState createState() {
return _nameFieldState;
}
}
class ProjectNameFieldState extends State<ProjectNameField> {
final myController = TextEditingController();
@override
void dispose() {
// Clean up the controller when the widget is disposed.
myController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return TextField(
controller: myController,
decoration: InputDecoration(
border: UnderlineInputBorder(),
hintText: PROJECTNAME,
),
maxLength: 30,
);
}
}
class ProjectDescriptionField extends StatefulWidget {
ProjectDescriptionFieldState _descriptionFieldState =
ProjectDescriptionFieldState();
@override
ProjectDescriptionFieldState createState() {
return _descriptionFieldState;
}
}
class ProjectDescriptionFieldState extends State<ProjectDescriptionField> {
final myController = TextEditingController();
@override
void dispose() {
// Clean up the controller when the widget is disposed.
myController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return TextField(
controller: myController,
decoration: InputDecoration(
border: UnderlineInputBorder(),
hintText: PROJECTDESCRIPTION,
),
minLines: 1,
maxLines: 5,
maxLength: 5000,
);
}
}
class SavedData {
String saved_Project_Name = "";
String saved_Project_Description = "";
List<Asset> saved_images = [];
SavedData(String saved_Project_Name, String saved_Project_Description,
List<Asset> saved_images) {
this.saved_Project_Name = saved_Project_Name;
this.saved_Project_Description = saved_Project_Description;
this.saved_images = saved_images;
}
}
我认为问题出在这里(ProjectNameField 和 ProjectDescriptionField 本质上是一样的,只有细微的差别):
class ProjectNameField extends StatefulWidget {
ProjectNameFieldState _nameFieldState = ProjectNameFieldState();
@override
ProjectNameFieldState createState() {
return _nameFieldState;
}
}
class ProjectNameFieldState extends State<ProjectNameField> {
final myController = TextEditingController();
@override
void dispose() {
// Clean up the controller when the widget is disposed.
myController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return TextField(
controller: myController,
decoration: InputDecoration(
border: UnderlineInputBorder(),
hintText: PROJECTNAME,
),
maxLength: 30,
);
}
}
当我让 createState() 返回 _nameFieldState 而不是 ProjectNameFieldState() 时,会发生以下错误:
The createState function for ProjectDescriptionField returned an old or invalid state instance: ProjectDescriptionField, which is not null, violating the contract for createState.
'package:flutter/src/widgets/framework.dart':
Failed assertion: line 4681 pos 7: 'state._widget == null'
但是,当我返回 ProjectNameFieldState() 时,则此代码
onPressed: () {
SavedData _savedData = SavedData(
savedName._nameFieldState.myController.value.text,
savedDescription
._descriptionFieldState.myController.value.text,
savedPage._addPageState.getImages());
print(_savedData.saved_Project_Description);
print(_savedData.saved_Project_Name);
print(_savedData.saved_images.toString());
saveNewProject(_savedData);
}
不保存项目名称。 我怎样才能摆脱这个错误并保存项目名称和项目描述? 谢谢!
答案 0 :(得分:0)
您可以使用 Form
和 TextFormFiled
小部件轻松将值保存在变量中并验证表单字段。
这是代码片段:
为 GlobalKey
小部件声明一个 Form
final _formKey = GlobalKey<FormState>();
在您将放置 Scaffold
的 TextFormFiled
正文中,添加 Form
小部件作为所有字段的父项
Form(
key: _formKey,
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.02, 0, 0),
child: Center(
child: Container(
height: logicalHeight * 0.05,
width: logicalWidth * 0.9,
child: TextFormField(
controller: projectNameController,
decoration: InputDecoration(
hintText: PROJECTNAME,
border: UnderlineInputBorder()),
maxLength: 30
validator: (value) {
if (value.isEmpty) {
return 'This is a required field';
}
return null;
},
onSaved: (value) => savedProjectName = value),
)),
),
Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.01, 0, 0),
child: ElevatedButton(
child: Text(PICKIMAGES),
onPressed: loadAssets,
)),
Center(
child: Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.01, 0, 0),
child: getWidget())),
Padding(
padding: EdgeInsets.fromLTRB(
logicalWidth * 0.05, distanceFromImages, logicalWidth * 0.05, 0),
child: Center(child: Container(child: TextFormField(
controller:projectDescriptionController ,
decoration: InputDecoration(
hintText: PROJECTDESCRIPTION,
border: UnderlineInputBorder()),
minLines: 1,
maxLines: 5,
maxLength: 5000,
validator: (value) {
if (value.isEmpty) {
return 'This is a required field';
}
return null;
},
onSaved: (value) => savedProjectDescription = value))),
),
]),
),
现在在您的 IconButton
的 onPressed
中验证表单并使用 save 函数将 TextFormField
值保存在您的变量中。
final form = _formKey.currentState;
if (form.validate()) {
form.save();
}
现在在上面的代码中,form.validate()
将调用 validator
,form.save()
将调用 onSaved
的 TextFormField
属性
完整代码如下:
import 'package:flutter/material.dart';
class AddPage extends StatefulWidget {
AddPage({Key? key}) : super(key: key);
@override
_AddPageState createState() =>
_AddPageState();
}
class _AddPageState extends State<AddPage> {
final _formKey = GlobalKey<FormState>();
String savedProjectName;
String savedProjectDescription;
final projectNameController = TextEditingController();
final projectDescriptionController = TextEditingController();
double logicalHeight; //your logical height
double logicalWidth; //your logical widgth
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: BackButton(color: Colors.white),
title: Text(CREATEPROJECT),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.check,
color: Colors.white,
),
onPressed: () {
final form = _formKey.currentState;
if (form.validate()) {
form.save();
}
},
),
],
),
body:Form(
key: _formKey,
child: Column(children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.02, 0, 0),
child: Center(
child: Container(
height: logicalHeight * 0.05,
width: logicalWidth * 0.9,
child: TextFormField(
controller: projectNameController,
decoration: InputDecoration(
hintText: PROJECTNAME,
border: UnderlineInputBorder()),
maxLength: 30,
validator: (value) {
if (value.isEmpty) {
return 'This is a required field';
}
return null;
},
onSaved: (value) => savedProjectName = value),
)),
),
Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.01, 0, 0),
child: ElevatedButton(
child: Text(PICKIMAGES),
onPressed: loadAssets,
)),
Center(
child: Padding(
padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.01, 0, 0),
child: getWidget())),
Padding(
padding: EdgeInsets.fromLTRB(
logicalWidth * 0.05, distanceFromImages, logicalWidth * 0.05, 0),
child: Center(child: Container(child: TextFormField(
controller:projectDescriptionController ,
decoration: InputDecoration(
hintText: PROJECTDESCRIPTION,
border: UnderlineInputBorder()),
minLines: 1,
maxLines: 5,
maxLength: 5000,
validator: (value) {
if (value.isEmpty) {
return 'This is a required field';
}
return null;
},
onSaved: (value) => savedProjectDescription = value),)),
),
]),
),
);
}
}