Flutter 将表单分解为多个小部件,并在flatter中与这些小部件交互
我有一个表单,我决定将其分解为多个小部件,以实现代码的可重用性。我遇到的问题是,我不知道如何与每个组件交互。例如,如果主窗体声明了一个变量,那么如何在存储在不同dart文件中的自定义textfield小部件中访问该变量 下面是我的代码 表单dart文件main.dartFlutter 将表单分解为多个小部件,并在flatter中与这些小部件交互,flutter,Flutter,我有一个表单,我决定将其分解为多个小部件,以实现代码的可重用性。我遇到的问题是,我不知道如何与每个组件交互。例如,如果主窗体声明了一个变量,那么如何在存储在不同dart文件中的自定义textfield小部件中访问该变量 下面是我的代码 表单dart文件main.dart import 'package:flutter/material.dart'; import 'package:finsec/widget/row_text_input.dart'; import 'package:finsec
import 'package:flutter/material.dart';
import 'package:finsec/widget/row_text_input.dart';
import 'package:finsec/widget/text_form_field.dart';
import 'package:finsec/widget/save_button.dart';
import 'package:finsec/utils/strings.dart';
import 'package:finsec/utils/dimens.dart';
import 'package:finsec/utils/colors.dart';
import 'package:finsec/widget/column_text_input.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Simple Interest Calculator App',
home: ThirdFragment(),
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.indigo,
accentColor: Colors.indigoAccent),
));
}
class ThirdFragment extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ThirdFragmentState();
}
}
class _ThirdFragmentState extends State<ThirdFragment> {
var _formKey = GlobalKey<FormState>();
var _currentItemSelected = '';
bool isError = false;
bool isButtonPressed = false;
@override
void initState() {
super.initState();
}
TextEditingController amountController = TextEditingController();
TextEditingController frequencyController = TextEditingController();
@override
Widget build(BuildContext context) {
TextStyle textStyle = Theme.of(context).textTheme.title;
return Scaffold(
appBar: AppBar(
title: Text('Simple Interest Calculator'),
),
body: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column (children: [
Padding(
padding: EdgeInsets.only(top: 10.0, bottom: 5.0, left: 15.0, right: 15.0),
child: CustomTextField(textInputType:TextInputType.number,
textController: amountController,
errorMessage:'Enter Income Amount',
labelText:'Income Amount for testing'),
),
RowTextInput(inputName: 'Frequency:',
textInputType: TextInputType.number,
textController: frequencyController,
errorMessage: 'Choose Income Frequency',
labelText: 'Income Amount for testing'
),
RowTextInput(inputName: 'Date Paid:',
textInputType: TextInputType.number,
textController: datePaidController,
errorMessage: 'Pick Income Payment Date',
labelText: 'Income Amount for testing'
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
MaterialButton(
height: margin_40dp,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(margin_5dp)),
minWidth: (MediaQuery.of(context).size.width * .9) / 2,
color: Theme.of(context).primaryColor,
textColor: white,
child: new Text(save),
onPressed: () => {
setState(() {
if (_formKey.currentState.validate()) {
// amountController.text.isEmpty ? amountController.text='Value require' : amountController.text='';
//this.displayResult = _calculateTotalReturns();
}
})
},
splashColor: blueGrey,
),
MaterialButton(
height: margin_40dp,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(margin_5dp)),
minWidth: (MediaQuery.of(context).size.width * .9) / 2,
color: Theme.of(context).primaryColor,
textColor: white,
child: new Text(save_and_continue),
onPressed: () => {},
splashColor: blueGrey,
)
])
]
),
),
}
我想从RowTextInput.dart访问main.dart中的isError和isButtonPressed变量,并能够赋值。然后main.dart应该能够看到在RowTextInput.dart文件中分配的那些值
此外,我想在自己的小部件文件button.dart中移动MaterialButton按钮,但我不知道当单击按钮或检查iError的值并按下按钮时,该dart文件将如何与main.dart文件交互。基本上,我将表单分解为不同的组件textfield和button,并将它们存储在各自独立的文件中。但是我希望所有文件main.dart、rowintputtext、button.dartnew都能够看到main.dart中变量的值并更改这些值。这可能吗?有没有更简单的方法
如果您仔细考虑的话,请提前感谢。在颤振中,按钮和RawMaterialButton已在其他文件中。而且他们能做到你想要的 您应该创建一个文件mycustomButtons.dart。 在这个文件中,你应该创建一个类来构建你的按钮。。。 但它的构造函数ActionSaveActionSave和Continue中必须有两个参数 然后,您将在main中创建两个函数,例如:
void _save() {
setState(() {
if (_formKey.currentState.validate()) {
// amountController.text.isEmpty ? amountController.text='Value require' : amountController.text='';
//this.displayResult = _calculateTotalReturns();
}
})
}
然后,应将创建的函数作为参数传递:
MyCustomButtons(actionSave: _save, actionSaveAndContinue: _saveAndContinue)
因此,按钮将包含更新main.dart变量所需的所有信息
文本字段基本相同。但您需要传递一个验证函数和一个TextEditingController
您可以查看RawnMaterialButton、TextFormField的字体,以查看它们如何从一个类接收数据并将数据传递到另一个类。。在颤振中,按钮和RawMaterialButton已在其他文件中。而且他们能做到你想要的 您应该创建一个文件mycustomButtons.dart。 在这个文件中,你应该创建一个类来构建你的按钮。。。 但它的构造函数ActionSaveActionSave和Continue中必须有两个参数 然后,您将在main中创建两个函数,例如:
void _save() {
setState(() {
if (_formKey.currentState.validate()) {
// amountController.text.isEmpty ? amountController.text='Value require' : amountController.text='';
//this.displayResult = _calculateTotalReturns();
}
})
}
然后,应将创建的函数作为参数传递:
MyCustomButtons(actionSave: _save, actionSaveAndContinue: _saveAndContinue)
因此,按钮将包含更新main.dart变量所需的所有信息
文本字段基本相同。但您需要传递一个验证函数和一个TextEditingController
您可以查看RawnMaterialButton、TextFormField的字体,以了解它们如何从一个类接收数据并将数据传递到另一个类。可能有一种更优雅的方法来实现这一点,但我目前正在试验单例。请参阅下面的代码:
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'dart:async';
class AppModel {
TextEditingController nameController;
TextEditingController surnameController;
StreamController<String> fullnameStreamController;
AppModel() {
nameController = TextEditingController();
surnameController = TextEditingController();
fullnameStreamController = StreamController.broadcast();
}
update() {
String fullname;
if (nameController.text != null && surnameController.text != null) {
fullname = nameController.text + ' ' + surnameController.text;
} else {
fullname = 'Please enter both names';
}
fullnameStreamController.add(fullname);
}
}
GetIt getIt = new GetIt();
final appModel = getIt.get<AppModel>();
void main() {
getIt.registerSingleton<AppModel>(AppModel());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Singleton Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String text;
update() {
setState(() {
});
}
@override
void initState() {
text = 'waiting for input';
appModel.fullnameStreamController.stream.listen((data) {
text = data;
update();
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(color: Colors.amberAccent),
child: Column(
children: <Widget> [
Card(
color: Colors.white,
child: Text('Name'),
),
Card(
color: Colors.yellow,
child: NameTextField()
),
Divider(),
Card(
color: Colors.white,
child: Text('Surname'),
),
Card(
color: Colors.yellow,
child: SurnameTextField()
),
OkButton(),
Card(
color: Colors.white,
child: Text('Full name'),
),
Card(
color: Colors.orange,
child: FullnameText(text),
),
],
),
),
);
}
}
class NameTextField extends StatefulWidget {
NameTextField({Key key}) : super(key: key);
_NameTextFieldState createState() => _NameTextFieldState();
}
class _NameTextFieldState extends State<NameTextField> {
@override
Widget build(BuildContext context) {
return Container(
child: TextField(
controller: appModel.nameController,
),
);
}
}
class SurnameTextField extends StatefulWidget {
SurnameTextField({Key key}) : super(key: key);
_SurnameTextFieldState createState() => _SurnameTextFieldState();
}
class _SurnameTextFieldState extends State<SurnameTextField> {
@override
Widget build(BuildContext context) {
return Container(
child: TextField(
controller: appModel.surnameController,
),
);
}
}
class FullnameText extends StatefulWidget {
FullnameText(this.text,{Key key}) : super(key: key);
final String text;
_FullnameTextState createState() => _FullnameTextState();
}
class _FullnameTextState extends State<FullnameText> {
@override
Widget build(BuildContext context) {
return Container(
child: Text(widget.text),
);
}
}
class OkButton extends StatefulWidget {
OkButton({Key key}) : super(key: key);
_OkButtonState createState() => _OkButtonState();
}
class _OkButtonState extends State<OkButton> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white10,
child: RaisedButton(
color: Colors.white,
child: Icon(Icons.check),
onPressed: () {appModel.update();},
),
);
}
}
检查我如何在AppModel类的更新函数中使用这三个控制器。可能有一种更优雅的方法来实现这一点,但我目前正在试验单例。请参阅下面的代码:
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'dart:async';
class AppModel {
TextEditingController nameController;
TextEditingController surnameController;
StreamController<String> fullnameStreamController;
AppModel() {
nameController = TextEditingController();
surnameController = TextEditingController();
fullnameStreamController = StreamController.broadcast();
}
update() {
String fullname;
if (nameController.text != null && surnameController.text != null) {
fullname = nameController.text + ' ' + surnameController.text;
} else {
fullname = 'Please enter both names';
}
fullnameStreamController.add(fullname);
}
}
GetIt getIt = new GetIt();
final appModel = getIt.get<AppModel>();
void main() {
getIt.registerSingleton<AppModel>(AppModel());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Singleton Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String text;
update() {
setState(() {
});
}
@override
void initState() {
text = 'waiting for input';
appModel.fullnameStreamController.stream.listen((data) {
text = data;
update();
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(color: Colors.amberAccent),
child: Column(
children: <Widget> [
Card(
color: Colors.white,
child: Text('Name'),
),
Card(
color: Colors.yellow,
child: NameTextField()
),
Divider(),
Card(
color: Colors.white,
child: Text('Surname'),
),
Card(
color: Colors.yellow,
child: SurnameTextField()
),
OkButton(),
Card(
color: Colors.white,
child: Text('Full name'),
),
Card(
color: Colors.orange,
child: FullnameText(text),
),
],
),
),
);
}
}
class NameTextField extends StatefulWidget {
NameTextField({Key key}) : super(key: key);
_NameTextFieldState createState() => _NameTextFieldState();
}
class _NameTextFieldState extends State<NameTextField> {
@override
Widget build(BuildContext context) {
return Container(
child: TextField(
controller: appModel.nameController,
),
);
}
}
class SurnameTextField extends StatefulWidget {
SurnameTextField({Key key}) : super(key: key);
_SurnameTextFieldState createState() => _SurnameTextFieldState();
}
class _SurnameTextFieldState extends State<SurnameTextField> {
@override
Widget build(BuildContext context) {
return Container(
child: TextField(
controller: appModel.surnameController,
),
);
}
}
class FullnameText extends StatefulWidget {
FullnameText(this.text,{Key key}) : super(key: key);
final String text;
_FullnameTextState createState() => _FullnameTextState();
}
class _FullnameTextState extends State<FullnameText> {
@override
Widget build(BuildContext context) {
return Container(
child: Text(widget.text),
);
}
}
class OkButton extends StatefulWidget {
OkButton({Key key}) : super(key: key);
_OkButtonState createState() => _OkButtonState();
}
class _OkButtonState extends State<OkButton> {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white10,
child: RaisedButton(
color: Colors.white,
child: Icon(Icons.check),
onPressed: () {appModel.update();},
),
);
}
}
检查我如何在AppModel类的更新函数中使用这三个控制器。我还希望将表单分解为多个类。这就是我所做的: 形式 在表单级别传递onSaved函数 最终_formKey=GlobalKey; @凌驾 小部件构建上下文上下文{ 报税表 键:_formKey, 子:列 crossAxisAlignment:crossAxisAlignment.start, 儿童:[ _CustomFormField onSaved:value=>\u myModelForm.field1=value, , _CustomFormField2 onSaved:value=>\u myModelForm.field2=value, , 升起的按钮 按下按钮:{ //如果表单有效,Validate将返回true;如果 //表格无效。 如果_formKey.currentState.validate{ //处理数据。 _formKey.currentState.save; //观察模型表单是否已更新 printmyModelForm.field1; printmyModelForm.field2 } }, 子:文本“提交”, , ], , ; } _CustomFormField1 onSaved函数将作为参数传递。此类可以位于与表单相同的文件中,也可以位于另一个专用文件中 类_CustomFormField1扩展了无状态小部件{ 保存最终表单设置器; //也许其他的财产。。。 _CustomFormField1{ @这是必需的。保存, }; @凌驾 小部件构建上下文上下文{ 返回填充 填充:常量边集。对称垂直:10.0, 子项:TextFormField //你可以把验证器放在这里 验证器:值{ 如果v 我是空的{ 返回“请输入一些文本”; } 返回null; }, 已保存:已保存, , ; } } 与onSaved一样,如果需要,您也可以对focusNode、onFieldSubmitted和validator执行相同的操作
我希望它能对您和其他人有所帮助我也在寻找将表单拆分为多个类的方法。这就是我所做的: 形式 在表单级别传递onSaved函数 最终_formKey=GlobalKey; @凌驾 小部件构建上下文上下文{ 报税表 键:_formKey, 子:列 crossAxisAlignment:crossAxisAlignment.start, 儿童:[ _CustomFormField onSaved:value=>\u myModelForm.field1=value, , _CustomFormField2 onSaved:value=>\u myModelForm.field2=value, , 升起的按钮 按下按钮:{ //如果表单有效,Validate将返回true;如果 //表格无效。 如果_formKey.currentState.validate{ //处理数据。 _formKey.currentState.save; //观察模型表单是否已更新 printmyModelForm.field1; printmyModelForm.field2 } }, 子:文本“提交”, , ], , ; } _CustomFormField1 onSaved函数将作为参数传递。此类可以位于与表单相同的文件中,也可以位于另一个专用文件中 类_CustomFormField1扩展了无状态小部件{ 保存最终表单设置器; //也许其他的财产。。。 _CustomFormField1{ @这是必需的。保存, }; @凌驾 小部件构建上下文上下文{ 返回填充 填充:常量边集。对称垂直:10.0, 子项:TextFormField //你可以把验证器放在这里 验证器:值{ 如果value.isEmpty{ 返回“请输入一些文本”; } 返回null; }, 已保存:已保存, , ; } } 与onSaved一样,如果需要,您也可以对focusNode、onFieldSubmitted和validator执行相同的操作
我希望它能帮助你和其他人谢谢你。只是想知道在我的新dart文件mycustomButtons.dart中,我是否需要声明为无状态或有状态小部件。谢天谢地,可能是个无国籍的人。国家将由TextFormFields本身控制。谢谢你。只是想知道在我的新dart文件mycustomButtons.dart中,我是否需要声明为无状态或有状态小部件。谢天谢地,可能是个无国籍的人。该州将由TextFormFields本身控制。这个答案对于我这个仍在学习的人来说非常有效,更加详细和清晰。这个答案对于我这个仍在学习的人来说非常有效,更加详细和清晰。