简体   繁体   English

从在 flutter 中的不同 class 上创建的自定义小部件访问数据

[英]Access data from custom widget created on different class in flutter

I new to Flutter and i was trying to find a solution for the below issue for several hours.我是 Flutter 的新手,我试图为以下问题找到解决方案几个小时。 I have searched and every solution provided does not work form me.我已经搜索过,提供的每个解决方案都对我不起作用。

I have page where one of the widgets is the autocomplete text input.我有一个页面,其中一个小部件是自动完成文本输入。 I have created this autocomplete widget on different class.我在不同的 class 上创建了这个自动完成小部件。 I have added this widget as StatefulBuilder within my main widget.我已将此小部件作为 StatefulBuilder 添加到我的主小部件中。 it is working fine however, i am not able to access its value so I can store it with other fields.它工作正常,但是我无法访问它的值,所以我可以将它与其他字段一起存储。

My code look like我的代码看起来像

class ItemDetails extends StatefulWidget {


const ItemDetails({Key? key}) : super(key: key);

  static const routeName = '/item_details';

  @override
  State<ItemDetails> createState() => _ItemDetails();
}

class _ItemDetails extends State<ItemDetails> {
  late TextEditingController labelController;
  late TextEditingController valueController;
  late TextEditingController notesController;

  bool _submitted = false;
  late var args;
  var labelAutoComp = LabelSugg();

  @override
  void initState() {
    super.initState();
    labelController = TextEditingController();
    valueController = TextEditingController();
    notesController = TextEditingController();
  }

  @override
  void dispose() {
    labelController.dispose();
    valueController.dispose();
    notesController.dispose();
    super.dispose();
  }

  String? _labelErrorText(context) {
    final text = labelController.value.text;
    if (text.isEmpty) {
      // return 'Can\'t be empty';
      return AppLocalizations.of(context)!.noEmpty;
    }
  }

  String? _valueErrorText(context) {
    final text = valueController.value.text;
    if (text.isEmpty) {
      // return 'Can\'t be empty';
      return AppLocalizations.of(context)!.noEmpty;
    }
  }

  @override
  Widget build(BuildContext context) {
    try {
      args = ModalRoute.of(context)!.settings.arguments as Map;
    } on Exception catch (e) {

  // print(e);
}

// print(args);
return Scaffold(
    appBar: AppBar(
      title: Text(args['title']),
    ),
    body: Container(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(20),
              child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    StatefulBuilder(builder: (context, setState) {
                      return labelAutoComp;
                    }),
                    TextField(
                      autofocus: true,
                      decoration: InputDecoration(
                        labelText: AppLocalizations.of(context)!.label,
                        hintText: AppLocalizations.of(context)!.labelHint,
                        errorText:
                            _submitted ? _labelErrorText(context) : null,
                      ),
                      controller: labelController,
                      onChanged: (_) => setState(() {}),
                    ),
                    const SizedBox(height: 5),
                    TextField(
                      autofocus: false,
                      decoration: InputDecoration(
                        labelText: AppLocalizations.of(context)!.value,
                        hintText: AppLocalizations.of(context)!.valueHint,
                        errorText:
                            _submitted ? _valueErrorText(context) : null,
                      ),
                      controller: valueController,
                      keyboardType: const TextInputType.numberWithOptions(
                          decimal: true, signed: false),
                      inputFormatters: <TextInputFormatter>[
                        FilteringTextInputFormatter.allow(
                            RegExp(r"[0-9.]")),
                        TextInputFormatter.withFunction(
                            (oldValue, newValue) {
                          try {
                            final text = newValue.text;
                            if (text.isNotEmpty) double.parse(text);
                            return newValue;
                          } catch (e) {}
                          return oldValue;
                        }),
                      ], // Only numbers can be entered
                      onChanged: (_) => setState(() {}),
                    ),
                    const SizedBox(height: 5),
                    TextField(
                      autofocus: true,
                      decoration: InputDecoration(
                        labelText: AppLocalizations.of(context)!.notes,
                        hintText: AppLocalizations.of(context)!.noteHint,
                      ),
                      controller: notesController,
                      onChanged: (_) => setState(() {}),
                    ),
                  ]),

              // ],
            ),
            Expanded(
              child: Align(
                  alignment: FractionalOffset.bottomCenter,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton.icon(
                        onPressed: () {
                          setState(() => _submitted = true);
                          if (_labelErrorText(context) == null &&
                              _valueErrorText(context) == null) {
                            //insert
                            var localLabel = labelController.value.text;

                            var _localValue = 0.0;
                            if (valueController.value.text != '') {
                              _localValue =
                                  double.parse(valueController.value.text);
                            } else {
                              _localValue = 0.0;
                            }

                            var localNotes = notesController.value.text;

                            addItemToList(
                                localLabel, _localValue, localNotes);
                            Navigator.of(context).pop();
                            labelController.clear();
                            valueController.clear();
                            notesController.clear();
                          }
                        },
                        label: Text(AppLocalizations.of(context)!.add),
                        icon: const Icon(Icons.save, size: 18),
                      ),
                      const SizedBox(width: 10),
                      ElevatedButton.icon(
                        onPressed: () => {Navigator.pop(context)},
                        label: Text(AppLocalizations.of(context)!.cancel),
                        icon: const Icon(Icons.cancel, size: 18),
                      ),
                    ],
                  )),
            ),
            // )
          ],
        )));

my labelAutoComp widget code look like我的 labelAutoComp 小部件代码看起来像

class LabelSugg extends StatefulWidget {
  const LabelSugg({Key? key}) : super(key: key);

  @override
  State<LabelSugg> createState() => _LabelSugg();
}

class _LabelSugg extends State<LabelSugg> {
  late TextEditingController fieldTextEditingController;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  getLabel() {
    return fieldTextEditingController.text;
  }

  @override
  Widget build(BuildContext context) {}
}

how to access the controller or the text entered in如何访问 controller 或输入的文本

StatefulBuilder(builder: (context, setState) {
 return labelAutoComp;
}),
  • first is redundant when you wrap your class that extend StatefullWidget with StatefullBuilder .当您包装扩展StatefullWidgetStatefullBuilderclass时, first 是多余的。 LabelSugg is a component Widget. LabelSugg是一个组件 Widget。 you can use it like other widget.你可以像其他小部件一样使用它。

  • benefit to separate widget with StatefullWidget class is, we can update the value inside the class without re-build the current page.使用StatefullWidget class 分离小部件的好处是,我们可以在不重新构建当前页面的情况下更新 class 内部的值。 which is good for performance.这对性能有好处。 that's why developer recomend to separete with class insted compared to make local method.这就是为什么开发人员建议与 class 分开安装,而不是使用本地方法。

  • as you see, when you create LabelSugg extend StatefullWidget class, we will have _LabelSugg .如您所见,当您创建LabelSugg扩展StatefullWidget class 时,我们将拥有_LabelSugg underscore means that: all variable only accessible on current file.下划线表示:所有变量只能在当前文件上访问。 thats why we can't call getLabel() or other variable from different file.这就是为什么我们不能从不同的文件中调用getLabel()或其他变量的原因。 its used for handle the State in 'LabelSugg` widget.它用于处理“ State ”小部件中的 State。


now how to pass the value from LabelSugg is by created variable outside the state.现在如何从LabelSugg传递值是通过在 state 之外创建的变量。 here you are:给你:

class LabelSugg extends StatefulWidget {
  // use this to pass any changes when we use LabelSugg
  final ValueChanged<String> getLabelText; 
  const LabelSugg({Key? key, required this.getLabelText}) : super(key: key);

  @override
  State<LabelSugg> createState() => _LabelSugg();
}

then we can call the onChaged inside _LabelSugg state.然后我们可以调用onChaged里面_LabelSugg because its Statefull widget, we can acces by: widget.getLabelText()因为它的 Statefull 小部件,我们可以通过以下方式访问: widget.getLabelText()

class _LabelSugg extends State<LabelSugg> {
  late TextEditingController fieldTextEditingController;
.....

getLabel() {
    return widget.getLabelText(fieldTextEditingController.text);
  }

then in other class we call LabelSugg like common widget然后在其他 class 中,我们将LabelSugg常见小部件

import 'package:../labelsug.dart';

class ItemDetails extends StatefulWidget {
.....

return Scaffold(
    appBar: AppBar(
      title: Text(args['title']),
    ),
    body: Container(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: <Widget>[
             // now use it like a widget 
             LabelSug(
                 getLabelText: (String val){
                     print(val);
                  }

:) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM