颤振中复选框的设置状态

时间:2021-05-24 20:22:37

标签: flutter

我已经按照另一个问题的答案之一在 flutter 中创建了一个可扩展的表单,但是当我向 createCard() 添加一个复选框时,我不能 SetState 并且复选框没有在应用程序中检查。这是没有复选框的原始代码:

import 'package:flutter/material.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          child: Text('Add entries'),
          onPressed: () async {
            List<PersonEntry> persons = await Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => SOF(),
              ),
            );
            if (persons != null) persons.forEach(print);
          },
        ),
      ),
    );
  }
}

class SOF extends StatefulWidget {
  @override
  _SOFState createState() => _SOFState();
}

class _SOFState extends State<SOF> {
  var nameTECs = <TextEditingController>[];
  var ageTECs = <TextEditingController>[];
  var jobTECs = <TextEditingController>[];
  var checkBools = <bool>[];
  var cards = <Card>[];

  Card createCard() {
    var nameController = TextEditingController();
    var ageController = TextEditingController();
    var jobController = TextEditingController();
    var checkBool = false;
    nameTECs.add(nameController);
    ageTECs.add(ageController);
    jobTECs.add(jobController);
    checkBools.add(checkBool);
    int cardIndex = cards.length;
    return Card(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text('Person ${cards.length + 1}'),
          TextField(
              controller: nameController,
              decoration: InputDecoration(labelText: 'Full Name')),
          TextField(
              controller: ageController,
              decoration: InputDecoration(labelText: 'Age')),
          TextField(
              controller: jobController,
              decoration: InputDecoration(labelText: 'Study/ job')),
          Checkbox(
                  activeColor: Colors.grey,
                  value: checkBools[cardIndex],
                  onChanged: (bool value) {
                    setState(() {
                      checkBools[cardIndex] = value;
                    });
                  },
                ),
        ],
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    cards.add(createCard());
  }

  _onDone() {
    List<PersonEntry> entries = [];
    for (int i = 0; i < cards.length; i++) {
      var name = nameTECs[i].text;
      var age = ageTECs[i].text;
      var job = jobTECs[i].text;
      var checkBoxInput = checkBools[i].toString();
      entries.add(PersonEntry(name, age, job, checkBoxInput));
    }
    Navigator.pop(context, entries);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          Expanded(
            child: ListView.builder(
              itemCount: cards.length,
              itemBuilder: (BuildContext context, int index) {
                return cards[index];
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: RaisedButton(
              child: Text('add new'),
              onPressed: () => setState(() => cards.add(createCard())),
            ),
          )
        ],
      ),
      floatingActionButton:
          FloatingActionButton(child: Icon(Icons.done), onPressed: _onDone),
    );
  }
}

class PersonEntry {
  final String name;
  final String age;
  final String studyJob;
  final String checkBoxInput;

  PersonEntry(this.name, this.age, this.studyJob);
  @override
  String toString() {
    return 'Person: name= $name, age= $age, study job= $studyJob, checkbox=$checkBoxInput';
  }
}

向 createCard() 添加复选框的最佳方法是什么?

更新:我已将代码更改为我尝试使用复选框的代码,但未在复选框上设置状态。

1 个答案:

答案 0 :(得分:1)

ListView 中的 CheckBox 似乎不会更新自己的状态,因此您需要将其包装在 StatefulBuilder 中。

这是您的代码,已修改以使复选框有效:

import 'package:flutter/material.dart';

void main() {
  runApp(App());
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          child: Text('Add entries'),
          onPressed: () async {
            List<PersonEntry> persons = await Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => SOF(),
              ),
            );
            if (persons != null) persons.forEach(print);
          },
        ),
      ),
    );
  }
}

class SOF extends StatefulWidget {
  @override
  _SOFState createState() => _SOFState();
}

class _SOFState extends State<SOF> {
  var nameTECs = <TextEditingController>[];
  var ageTECs = <TextEditingController>[];
  var jobTECs = <TextEditingController>[];
  var checkBools = <bool>[];
  var cards = <Card>[];

  Card createCard() {
    var nameController = TextEditingController();
    var ageController = TextEditingController();
    var jobController = TextEditingController();
    var checkBool = false;
    nameTECs.add(nameController);
    ageTECs.add(ageController);
    jobTECs.add(jobController);
    checkBools.add(checkBool);
    int cardIndex = cards.length;
    return Card(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text('Person ${cards.length + 1}'),
          TextField(
              controller: nameController,
              decoration: InputDecoration(labelText: 'Full Name')),
          TextField(
              controller: ageController,
              decoration: InputDecoration(labelText: 'Age')),
          TextField(
              controller: jobController,
              decoration: InputDecoration(labelText: 'Study/ job')),
          StatefulBuilder(
            builder: (BuildContext context, StateSetter setState) {
              return Checkbox(
                activeColor: Colors.grey,
                value: checkBools[cardIndex],
                onChanged: (bool value) {
                  setState(() {
                    checkBools[cardIndex] = value;
                  });
                },
              );
            },
          ),
        ],
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    cards.add(createCard());
  }

  _onDone() {
    List<PersonEntry> entries = [];
    for (int i = 0; i < cards.length; i++) {
      var name = nameTECs[i].text;
      var age = ageTECs[i].text;
      var job = jobTECs[i].text;
      var checkBoxInput = checkBools[i].toString();
      entries.add(PersonEntry(name, age, job, checkBoxInput));
    }
    Navigator.pop(context, entries);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          Expanded(
            child: ListView.builder(
              itemCount: cards.length,
              itemBuilder: (BuildContext context, int index) {
                return cards[index];
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: RaisedButton(
              child: Text('add new'),
              onPressed: () => setState(() => cards.add(createCard())),
            ),
          )
        ],
      ),
      floatingActionButton:
          FloatingActionButton(child: Icon(Icons.done), onPressed: _onDone),
    );
  }
}

class PersonEntry {
  final String name;
  final String age;
  final String studyJob;
  final String checkBoxInput;

  PersonEntry(this.name, this.age, this.studyJob, this.checkBoxInput);
  @override
  String toString() {
    return 'Person: name= $name, age= $age, study job= $studyJob, checkbox=$checkBoxInput';
  }
}