我在运行时收到一个JSON对象列表,并基于这些JSON对象动态创建一个liderWidget列表(见下图).当我按下FloatingActionButton时,我需要在父小部件(作为主屏幕)中访问这些liderWidget的slderValues,因为这会将gliderValues保存到CSV文件中.我怎么能在不做一些非常难看的事情的情况下访问滑动值呢?由于该列表是在运行时动态创建的,并且其中可能包含大量对象,因此我不确定该如何执行此操作.

enter image description here

我试图用 keys 访问这些物品,但无济于事.我也不确定这是否是最好的做法.

以下代码省略了不重要的部分

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

  @override
  State<MorningSurveyScreen> createState() => _MorningSurveyScreenState();
}

class _MorningSurveyScreenState extends State<MorningSurveyScreen> {

  late List<Widget> _userVariablesWidgets; // This is the variable where I save my sliderWidget list

  didChangeDependencies() {
    super.didChangeDependencies();

    _userVariablesWidgets = UserVariablesHelper.getUserVariablesWidgets(Provider.of<UserVariablesModel>(context, listen: true).userVariables); 
// This is where I start listening for my list of sliderWidgets
  }
  
  Future<void> _addEntry() async {
    bool addEntry = await DialogHelper.showAddEntryDialog(context);
    if (addEntry) {
      await CsvDataService.addRowToCsv({
        // THIS POINT IS WHERE I NEED TO ACCESS THE SLIDER VALUES
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    //wrap in consumer
    return Consumer<UserVariablesModel>(
        builder: (context, userVariablesModel, child) => Stack(
              children: [
                Center(
                  child: ListView(
                    children: <Widget>[
                      // OTHER WIDGETS,
                      ..._userVariablesWidgets // These are my sliderWidgets
                    ],
                  ),
                ),
                Positioned(
                  bottom: 16,
                  right: 16,
                  child: FloatingActionButton(
                    onPressed: _addEntry,
                    tooltip: 'Add entry',
                    child: const Icon(Icons.check),
                  ),
                )
              ],
            ));
  }
}

为了完整性,这些是我的SliderWidget,也是为了可读性而精简的

class SliderWidget extends StatefulWidget {
  final SliderVariable sliderVariable;
  // This holds sliderWidget min, max values and question label.
  // However, it is unimportant for us right now

  SliderWidget({Key? key, required this.sliderVariable});

  @override
  State<SliderWidget> createState() => _SliderWidgetState();
}

class _SliderWidgetState extends State<SliderWidget> {
  late double currentSliderValue = widget.sliderVariable.min.toDouble();
// This is the value I need to access from my MorningSurveyScreen

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // OTHER WIDGETS,
        Slider(
          value: currentSliderValue,
          min: widget.sliderVariable.min.toDouble(),
          max: widget.sliderVariable.max.toDouble(),
          divisions: widget.sliderVariable.max - widget.sliderVariable.min,
          label: currentSliderValue.round().toString(),
          onChanged: (double value) {
            setState(() {
              currentSliderValue = value;
            });
          },
        )
      ],
    );
  }
}

推荐答案

在这里,我举了一个例子,说明如何使用您已经使用过的Provider个包来实现它,这样您就可以根据您的需要进行调整. 以下是UserVariablesModel提供程序示例:

import 'package:flutter/material.dart';

class UserVariablesModel with ChangeNotifier {
  final List<SliderVariable> _userVariables = [
    SliderVariable(min: 0, max: 10, question: 'How would you rate your sleep?'),
    SliderVariable(
        min: 0,
        max: 10,
        question: 'How many times did you wake up in the night?'),
  ];

  List<SliderVariable> get userVariables => List.unmodifiable(_userVariables);

  updateVariable(SliderVariable sliderVariable, double value) {
    final index = userVariables.indexOf(sliderVariable);
    if (index != -1) {
      _userVariables[index] = sliderVariable.copyWith(value: value);
      notifyListeners();
    }
  }
}

class SliderVariable {
  double min;
  double max;
  double value;
  String question;

  SliderVariable({
    required this.min,
    required this.max,
    double? value,
    required this.question,
  }) : value = value ?? min;

  SliderVariable copyWith({
    double? min,
    double? max,
    double? value,
    String? question,
  }) {
    return SliderVariable(
      min: min ?? this.min,
      max: max ?? this.max,
      value: value ?? this.value,
      question: question ?? this.question,
    );
  }
}

这是如何使用它来反映变化的示例:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:test/business/user_variables_model.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => UserVariablesModel(),
      child: const MaterialApp(
        home: Scaffold(
          body: SafeArea(
            child: MorningSurveyScreen(),
          ),
        ),
      ),
    );
  }
}

class MorningSurveyScreen extends StatelessWidget {
  const MorningSurveyScreen({Key? key}) : super(key: key);

  Future<void> _addEntry(List<SliderVariable> sliderVariables) async {
    print("slider values:");
    for (var userVariable in sliderVariables) {
      print(userVariable.value);
    }

    // bool addEntry = await DialogHelper.showAddEntryDialog(context);
    // if (addEntry) {
    //   await CsvDataService.addRowToCsv({
    //     // THIS POINT IS WHERE I NEED TO ACCESS THE SLIDER VALUES
    //   });
    // }
  }

  @override
  Widget build(BuildContext context) {
    //wrap in consumer
    return Consumer<UserVariablesModel>(
      builder: (context, userVariablesModel, child) => Stack(
        children: [
          Center(
            child: ListView(
              children: <Widget>[
                // OTHER WIDGETS,
                for (var sliderVariable in userVariablesModel.userVariables)
                  SliderWidget(sliderVariable: sliderVariable)
              ],
            ),
          ),
          Positioned(
            bottom: 16,
            right: 16,
            child: FloatingActionButton(
              onPressed: () => _addEntry(userVariablesModel.userVariables),
              tooltip: 'Add entry',
              child: const Icon(Icons.check),
            ),
          )
        ],
      ),
    );
  }
}

class SliderWidget extends StatelessWidget {
  final SliderVariable sliderVariable;

  const SliderWidget({Key? key, required this.sliderVariable})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    final currentSliderValue = sliderVariable.value.toDouble();
    return Column(
      children: [
        // OTHER WIDGETS,
        Slider(
          value: currentSliderValue,
          min: sliderVariable.min.toDouble(),
          max: sliderVariable.max.toDouble(),
          divisions: (sliderVariable.max - sliderVariable.min).toInt(),
          label: currentSliderValue.round().toString(),
          onChanged: (double value) {
            Provider.of<UserVariablesModel>(context, listen: false)
                .updateVariable(sliderVariable, value);
          },
        )
      ],
    );
  }
}

Flutter相关问答推荐

Flutter:sqflite DB

Flutter Go路由深度链接不按预期工作

带有可滚动页面(不包括分页区)的Flutter 页面视图

如何防止onTapCancel由子元素触发?

如何知道当前屏幕是否处于抖动状态?

如何使页面浏览量达到活动页面所要求的高度?

无法构建AndroidBundle 包或iOS等

怎么才能像这样在摆动着这些曲线呢?

任务';:app:check DebugDuplicateClasss';的Ffltter Share_plus抛出执行失败

如何在Flutter 中使用滚动展开窗口小部件

Flutter-Riverpod:如何只从提供者读取一次值

带有附加图像的ListTile

Dart 和 flutter 错误无法在您的 PATH 中找到 git

Flutter:使用 GlobalKey 访问 BlocProvider

如何将取消图标放置在右上角

点击按钮后重新启动定时器

应用程序包含嵌入式私钥或密钥库文件

使用 mocktail 包进行单元测试时,类型Null不是Future类型的子类型

type '_InternalLinkedHashMap' 不是使用 http 包的'String' 类型的子类型

如何在Flutter 中制作自定义微调器?