【问题标题】:Checking one CheckBox in a ListView checks all of the rest using Flutter检查 ListView 中的一个 CheckBox 使用 Flutter 来检查所有其余的 CheckBox
【发布时间】:2020-09-07 15:00:33
【问题描述】:

我对 Flutter 和 Stackoverflow 完全陌生。事实上,这是我的第一个问题,所以如果我完全没有提出这个问题,请原谅我。我正在尝试制作一个简单的 Flutter 应用程序,它提供问题的 ListView 和每个问题旁边的复选框。然后用户可以选择他们想要回答的问题。我的问题是,当用户选中任何复选框时,所有复选框都会被选中,反之亦然。问题本身是从无后端数据库中检索的。下面的代码是我到目前为止所拥有的。任何人都可以为我提供任何帮助,我将不胜感激。

import 'package:flutter/material.dart';

class Questions extends StatefulWidget {
  final List<Map> questionList;

  Questions(this.questionList);

  @override
  _QuestionsState createState() => _QuestionsState();
}

class _QuestionsState extends State<Questions> {
  bool _questionSelected = true;

  Widget _buildQuestionItem(BuildContext context, int index) {
    return ListTile(
      title: Text(widget.questionList[index]['question']),
      trailing: Checkbox(
        value: _questionSelected,
        onChanged: (bool val){
          setState(() {
            _questionSelected = val;
          });
        },
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      padding: EdgeInsets.all(10),
      itemBuilder: _buildQuestionItem,
      itemCount: widget.questionList.length,
    );
  }
}

更新:

感谢 Mohammed Ashab Uddin 的建议我觉得我已经接近让这个东西工作但我仍然收到错误

"RangeError(index):无效值:有效值范围为空:0"

我想我应该在我设置 questionList 值的地方发布 main.dart 代码,也许它是导致此错误的代码执行顺序,所以请在下面找到我的 main.dart 代码,希望它会有所帮助解决这个问题。

import 'package:flutter/material.dart';
import 'package:backendless_sdk/backendless_sdk.dart';
import 'package:flutter/rendering.dart';

import 'questions.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'RT Database Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Questions'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  static const String API_HOST = "https://api.backendless.com";
  static const String APP_ID = "<APP_ID>";
  static const String ANDROID_APP_KEY = "<ANDROID_APP_KEY>";
  static const String IOS_APP_KEY = "<IOS_APP_KEY>";

  IDataStore<Map> questionsStore = Backendless.data.of('Questions');
  List<Map> questionsList = [];
  var _questionSelected = false;

  @override
  void initState() {
    super.initState();
    _initBackendless();
    _enableRealTime();
    getQuestions();
  }

  void _initBackendless() {
    Backendless.setUrl(API_HOST);
    Backendless.initApp(APP_ID, ANDROID_APP_KEY, IOS_APP_KEY);
  }

  void _enableRealTime() {
    EventHandler<Map> rtHandlers = questionsStore.rt();

    rtHandlers.addCreateListener((question) {
      setState(() {
        questionsList = List.from(questionsList);
        questionsList.add(question);
      });
    });

    rtHandlers.addUpdateListener((question) {
      setState(() {
        questionsList = List.from(questionsList
            .map((m) => m['objectId'] == question['objectId'] ? question : m));
      });
    });

    rtHandlers.addDeleteListener((question) {
      setState(() {
        questionsList = List.from(questionsList);
        questionsList.removeWhere((m) => m['objectId'] == question['objectId']);
      });
    });
  }

  void _selectQuestion(bool newValue) {
    setState(() {
      _questionSelected = newValue;
    });
  }

  void getQuestions() {
    DataQueryBuilder queryBuilder = DataQueryBuilder()
      ..pageSize = 100
      ..sortBy = ['created'];

    questionsStore
        .find(queryBuilder)
        .then((response) => setState(() => questionsList = response));
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text("My Life History"),
      ),
      body: FractionallySizedBox(
        heightFactor: 0.5,
        child: Questions(questionsList),
      ),
    );
  }
}

【问题讨论】:

    标签: android listview flutter dart checkbox


    【解决方案1】:

    变量_questionSelected 是一个全局变量。所有复选框小部件都使用此变量作为值。因此,当onChanged()函数上的变量发生变化时,所有的值也会变为_questionSelected的值。

    在这种情况下,您需要跟踪复选框小部件的所有值。因此,您应该使用数组而不是单个变量。

    我通常做的是,创建一个仅包含所选元素的新列表。 如果一个元素没有被选中,则删除它,如果它被选中,则添加一个元素。

    //generate a list of false values with the length of questionList
    List<bool> _questionSelected;
    
    initState(){
       _questionSelected = List<bool>.filled(questionList.length, false, growable: true);
       super.initState();
    }
    
      Widget _buildQuestionItem(BuildContext context, int index) {
        return ListTile(
          title: Text(widget.questionList[index]['question']),
          trailing: Checkbox(
            value: _questionSelected[index],
            onChanged: (bool val){
              setState(() {
                _questionSelected[index] = val;
              });
            },
          ),
        );
      }
    

    【讨论】:

    • 当我按照上面的建议编辑代码时,填充方法的长度变量出现错误。它说只有静态成员可以在初始化程序中访问。我尝试阅读该错误的 dart 诊断消息,但无法理解它的含义以及它如何应用于我的代码。
    • 我忘了说你需要在initState()中初始化_questionSelected的值。我再次编辑了我的代码。
    • 我收到一个 RangeError,我觉得这可能是因为代码执行的顺序。我忘记在我的原始帖子中包含调用 questions.dart 代码的 main.dart 代码。我编辑了帖子以包含该代码,希望它可以给出 RangeError 来源的一些指示。我自己想不通。我应该补充一点,如果我在代码的填充方法中用数字 3 替换“questionList.length”,它就可以工作。我感觉在 questions.dart 被调用的时候,questionList 没有被初始化。这就是为什么我还发布了调用 questions.dart 的 main.dart
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 2017-01-31
    • 2012-06-20
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    • 2015-08-24
    相关资源
    最近更新 更多