如何从调用构建器的位置访问 ListViewBuilder 中的变量?

How to access a variable inside a ListViewBuilder from where the builder is called?

我正在开发一个应用程序,该应用程序的表单使用 ListViewBuilder 作为项目列表,returns 一个小部件为列表中的每个项目显示一个 TextField。有没有办法从表单小部件本身访问任何项目的 TextField 控制器以获取新值?

ListView 构建器中使用的小部件

class BrandNamesWidget extends StatelessWidget {
  BrandNamesWidget({Key? key, required this.brandName, required this.index})
      : super(key: key);
  final String brandName;
  final int index;

  final TextEditingController _brandNameController =
      new TextEditingController();

  @override
  Widget build(BuildContext context) {
    _brandNameController.text = brandName;
    final deviceDimensions = Provider.of<Dimension>(context);

    double height = deviceDimensions.getDeviceHeight();
    double width = deviceDimensions.getDeviceWidth();
    return TextField(
      controller: _brandNameController,
      cursorColor: Colors.black,
      style: TextStyle(
        color: AppInfo.MAIN_COLOR,
        letterSpacing: 1.5,
      ),
      keyboardType: TextInputType.text,
      decoration: InputDecoration(
        constraints: BoxConstraints(maxWidth: width * 0.45),
        labelText: 'Brand name: ' + index.toString(),
        prefixIcon: Icon(Icons.medication),
        labelStyle: TextStyle(
          fontSize: height * 0.03,
          color: AppInfo.MAIN_COLOR,
        ),
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(50),
        ),
      ),
    );
  }
}


表单小部件

.
.
Container(
                  child: ListView.builder(
                      itemCount: _brandnames.length,
                      itemBuilder: (BuildContext ctx, int index) {
                        return BrandNamesWidget(
                            brandName: _brandnames[index].toString(),
                            index: index);
                      }),
                ),

// Want to access the _brandNameController.text here in a function to update firestore
.
.

我已经在线查看解决方案,我发现的唯一类似问题来自这个 Whosebug 问题 (Is there a way to access variables in a state in Flutter/Dart?)

一种方法是在 itemBuilder 中从外部实例化一个 TextEditingController 并将其注入到 BrandNamesWidget 中,将它们的引用保存在一个集合中,这样您就可以获取它们像这样的外部内容 Gist 我为您创建。这就是您的新 class 的样子:

class BrandNamesWidget extends StatelessWidget {
  
  final TextEditingController? controller;
  final String? brandName;
  final int? index;
  
  BrandNamesWidget({ this.brandName, required this.index, this.controller });
  
  @override
  Widget build(BuildContext context) {
    
    double height = 100;
    double width = MediaQuery.of(context).size.width;
    
    return TextField(
      controller: controller!,
      keyboardType: TextInputType.text,
      decoration: InputDecoration(
        constraints: BoxConstraints(maxWidth: width * 0.45),
        labelText: 'Brand name: ' + index.toString(),
        prefixIcon: const Icon(Icons.medication),
        labelStyle: TextStyle(
          fontSize: height * 0.03,
          color: Colors.grey,
        ),
        border: OutlineInputBorder(
          borderRadius: BorderRadius.circular(50),
        ),
      ),
    );
  }
}

这是保留 TextEditingController 引用的父小部件,容纳您的 ListView.builder:


class MyWidget extends StatelessWidget {
  
  List<String> _brandnames = ['Toyota', 'Honda', 'BMW', 'Mercedes'];
  List<TextEditingController> controllers = [];
  
  @override
  Widget build(BuildContext context) {
    
    controllers = [];
    
    return Column(
      children: [
        Expanded(
          child:  Container(
            child: ListView.builder(
              itemCount: _brandnames.length,
              itemBuilder: (BuildContext ctx, int index) {
                TextEditingController ctrl = TextEditingController();
                controllers.add(ctrl);
                return BrandNamesWidget(
                  brandName: _brandnames[index].toString(),
                  controller: ctrl,
                  index: index);
              }),
          )
        ),
        TextButton(
          onPressed: () {
            
            for(var ctrl in controllers) {
              print(ctrl.text);
            }
          },
          child: Text('Click me to get their values')
        )
      ]
    );
  }
}

如果您在显示的文本字段中输入内容,然后单击我提供的按钮,您将从一个函数中获取它们的内容,从而能够更新 Firestore 或任何您想要的内容。检查一下并告诉我。