Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 将表单分解为多个小部件,并在flatter中与这些小部件交互_Flutter - Fatal编程技术网

Flutter 将表单分解为多个小部件,并在flatter中与这些小部件交互

Flutter 将表单分解为多个小部件,并在flatter中与这些小部件交互,flutter,Flutter,我有一个表单,我决定将其分解为多个小部件,以实现代码的可重用性。我遇到的问题是,我不知道如何与每个组件交互。例如,如果主窗体声明了一个变量,那么如何在存储在不同dart文件中的自定义textfield小部件中访问该变量 下面是我的代码 表单dart文件main.dart import 'package:flutter/material.dart'; import 'package:finsec/widget/row_text_input.dart'; import 'package:finsec

我有一个表单,我决定将其分解为多个小部件,以实现代码的可重用性。我遇到的问题是,我不知道如何与每个组件交互。例如,如果主窗体声明了一个变量,那么如何在存储在不同dart文件中的自定义textfield小部件中访问该变量

下面是我的代码

表单dart文件main.dart

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本身控制。这个答案对于我这个仍在学习的人来说非常有效,更加详细和清晰。这个答案对于我这个仍在学习的人来说非常有效,更加详细和清晰。