我正在尝试使用块模式来管理我的复选框集。团体只需要存储是否选中该复选框即可。
下面是可以运行以模拟正在发生的事情的代码。
我得到的(错误)结果是,当您更新复选框时,数据无法正确呈现。
日志
First Click in Checkbox 1
I/flutter ( 6239): newMapCheckbox: {1: true}
I/flutter ( 6239): _mapCheckbox: {1: true, 2: false, 3: false}
Second Click in Checkbox 1
I/flutter ( 6239): newMapCheckbox: {1: null}
I/flutter ( 6239): _mapCheckbox: {1: null, 2: false, 3: false}
代码
import 'package:flutter/material.dart';
import 'dart:collection';
import 'package:rxdart/rxdart.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Checkbox Test',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
ApplicationBloc _bloc = new ApplicationBloc();
return Scaffold(
appBar: AppBar(
title: Text('Checkbox Test'),
),
body: StreamBuilder(
stream: _bloc.listItemModel,
builder:
(BuildContext context, AsyncSnapshot<List<ItemModel>> snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
List<ItemModel> listItemModel = snapshot.data;
return ListView.builder(
shrinkWrap: true,
itemCount: listItemModel.length,
itemBuilder: (context, index) {
ItemModel itemModel = listItemModel[index];
return ListTile(
leading: _checkbox(_bloc, itemModel.id),
title: Text('${itemModel.name}'),
);
},
);
},
),
);
}
_checkbox(ApplicationBloc _bloc, int idItemModel) {
// This doesn't render like expected
return StreamBuilder(
stream: _bloc.checkboxController,
builder: (BuildContext context, AsyncSnapshot<Map<int, bool>> snapshot) {
if (snapshot.hasData) {
return Checkbox(
tristate: true,
value: snapshot.data[idItemModel],
onChanged: (value) => _bloc.setCheckbox(
<int, bool>{idItemModel: value},
),
);
} else
return Container();
},
);
}
}
class ItemModel {
int id;
String name;
ItemModel(this.id, this.name);
}
class ApplicationBloc {
// List Management
BehaviorSubject<List<ItemModel>> listModelController =
BehaviorSubject<List<ItemModel>>();
Observable<List<ItemModel>> get listItemModel => listModelController.stream;
// Checkbox Management - Item Model ID and checkbox value
BehaviorSubject<Map<int, bool>> checkboxController =
BehaviorSubject<Map<int, bool>>();
Observable<Map<int, bool>> get mapModelCheckbox => checkboxController.stream;
Function(Map<int, bool>) get setCheckbox => checkboxController.sink.add;
List<ItemModel> _listItemModel = List<ItemModel>();
Map<int, bool> _mapCheckbox = HashMap<int, bool>();
ApplicationBloc() {
// Initial data for list and map
_listItemModel.add(ItemModel(1, 'Item Model 1'));
_mapCheckbox[1] = false;
_listItemModel.add(ItemModel(2, 'Item Model 2'));
_mapCheckbox[2] = false;
_listItemModel.add(ItemModel(3, 'Item Model 3'));
_mapCheckbox[3] = false;
// Insert initial data in controller
listModelController.add(_listItemModel);
checkboxController.add(_mapCheckbox);
// Handler for checkbox state
checkboxController.stream.listen(setCheckboxHandler);
}
setCheckboxHandler(Map<int, bool> newMapCheckbox) {
// New checkbox value for the itemModel id
int id = newMapCheckbox.entries.elementAt(0).key;
bool check = newMapCheckbox.entries.elementAt(0).value;
if (_mapCheckbox.containsKey(id)) {
_mapCheckbox[id] = check;
}
print('-----------');
print('newMapCheckbox: $newMapCheckbox');
print('_mapCheckbox: $_mapCheckbox');
print('-----------');
}
//dispose/close all the streams when we call dispose() method
void dispose() {
listModelController.close();
checkboxController.close();
}
}
答案 0 :(得分:0)
对于您所需要的,您只应在复选框中管理两个状态。
以代码为基础,我们有这样的东西。
import 'package:flutter/material.dart';
import 'dart:collection';
import 'package:rxdart/rxdart.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter CheckboxListTile',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Demo(),
);
}
}
// model amenities.
class Item {
int id;
String title;
Item({this.id, this.title});
List<String> _amenities = [
"Item Model 1",
"Item Model 2",
"Item Model 3",
];
List<String> getAm(
Map<int, bool> checkBoxes, Map<int, String> checkAmenities) {
List<String> _am = [];
for (var i = 0; i < checkBoxes.length; i++) {
if (checkBoxes[i] != false) {
print(i);
print(checkAmenities[i]);
_am.add(checkAmenities[i]);
}
}
return _am;
}
List<Item> getItems() {
List<Item> _items = [];
for (var i = 0; i < _amenities.length; i++) {
_items.add(Item(id: i, title: _amenities[i]));
}
return _items;
}
}
class Demo extends StatelessWidget {
@override
Widget build(BuildContext context) {
Item _item = Item();
List<Item> checkBoxList = _item.getItems();
AmenitiesBloc _bloc = new AmenitiesBloc();
return new Scaffold(
appBar: new AppBar(title: new Text('CheckboxListTile demo')),
body: Container(
height: 225.0,
child: Card(child: grupCheck(checkBoxList, _bloc)),
),
);
}
ListView grupCheck(List<Item> checkBoxList, AmenitiesBloc _bloc) {
return new ListView.builder(
itemCount: checkBoxList.length,
itemBuilder: (BuildContext context, int index) {
return new Container(
padding: new EdgeInsets.all(0.0),
child: new Column(
children: <Widget>[
StreamBuilder<Object>(
stream: _bloc.checkboxController,
builder: (context, snapshot) {
return new CheckboxListTile(
activeColor:
Colors.green, //Check is true color is green
dense: true, //font change
value: _bloc._mapCheckbox[index],
title: new Text(checkBoxList[index].title),
controlAffinity: ListTileControlAffinity
.leading, //Display check box first, remove this line checkbox display last
onChanged: (value) =>
_bloc.setCheckbox(<int, bool>{index: value}),
);
})
],
),
);
});
}
}
// The bloc
class AmenitiesBloc {
// Checkbox Management - Item Model ID and checkbox value
BehaviorSubject<Map<int, bool>> checkboxController =
BehaviorSubject<Map<int, bool>>();
Stream<Map<int, bool>> get mapModelCheckbox => checkboxController.stream;
Function(Map<int, bool>) get setCheckbox => checkboxController.sink.add;
Item _item = Item();
Map<int, bool> _mapCheckbox = HashMap<int, bool>();
Map<int, String> _mapAmenities = HashMap<int, String>();
AmenitiesBloc() {
// Initial data for list and map
List<Item> _theAmenities = _item.getItems();
for (var i = 0; i < _theAmenities.length; i++) {
_mapAmenities[i] = _theAmenities[i].title;
_mapCheckbox[i] = false;
}
// Insert initial data in controller
checkboxController.add(_mapCheckbox);
checkboxController.stream.listen(setCheckboxHandler);
}
// Handler for checkbox state
setCheckboxHandler(Map<int, bool> newMapCheckbox) {
// New checkbox value for the itemModel id
int id = newMapCheckbox.entries.elementAt(0).key;
bool check = newMapCheckbox.entries.elementAt(0).value;
if (_mapCheckbox.containsKey(id)) {
_mapCheckbox[id] = check;
}
print('-----------');
print('newMapCheckbox: $newMapCheckbox');
print('_mapCheckbox: $_mapCheckbox');
print('-----------');
print(_mapCheckbox.length);
List<String> a = _item.getAm(_mapCheckbox, _mapAmenities);
print(a.toString());
print(a.toString().runtimeType);
}
//dispose/close all the streams when we call dispose() method
void dispose() {
checkboxController.close();
}
}