group.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import 'package:flutter/material.dart';
  2. import 'cell.dart';
  3. typedef VCheckBoxCellGroupItemBuilder<T> = Widget Function(T data);
  4. typedef VCheckBoxCellGroupCheckChanged<T, TValue> = void Function(
  5. TValue value,
  6. bool isChecked,
  7. T data,
  8. List<TValue> checkedValues,
  9. );
  10. class CheckBoxCellGroupItem<T> {
  11. final T data;
  12. final bool isChecked;
  13. final bool isDisabled;
  14. CheckBoxCellGroupItem(
  15. this.data, {
  16. this.isChecked = false,
  17. this.isDisabled = false,
  18. });
  19. }
  20. class VCheckBoxCellGroup<T, TValue> extends StatefulWidget {
  21. final List<CheckBoxCellGroupItem<T>> source;
  22. /// 选项文本提取函数
  23. final String Function(T data) labelGetter;
  24. /// 选项值提取函数
  25. final TValue Function(T data) valueGetter;
  26. final VCheckBoxCellGroupCheckChanged<T, TValue>? onChanged;
  27. final bool isScrollable;
  28. final ScrollController? controller;
  29. const VCheckBoxCellGroup({
  30. super.key,
  31. required this.source,
  32. required this.labelGetter,
  33. required this.valueGetter,
  34. this.onChanged,
  35. this.isScrollable = true,
  36. this.controller,
  37. });
  38. @override
  39. State<StatefulWidget> createState() => _VCheckBoxCellGroupState<T, TValue>();
  40. }
  41. class _VCheckBoxCellGroupState<T, TValue>
  42. extends State<VCheckBoxCellGroup<T, TValue>> {
  43. List<TValue> _checkedValues = [];
  44. @override
  45. void initState() {
  46. _checkedValues = widget.source
  47. .where((e) => e.isChecked)
  48. .map((e) => widget.valueGetter.call(e.data))
  49. .toList();
  50. super.initState();
  51. }
  52. @override
  53. Widget build(BuildContext context) {
  54. final divider = Divider(
  55. thickness: 1,
  56. color: Colors.grey.shade300,
  57. height: 2,
  58. );
  59. final children = <Widget>[];
  60. final count = widget.source.length;
  61. for (var i = 0; i < count; i++) {
  62. if (i > 0) {
  63. children.add(divider);
  64. }
  65. final item = widget.source[i];
  66. children.add(_buildItemWidget(item));
  67. }
  68. if (widget.isScrollable) {
  69. return ListView(
  70. shrinkWrap: true,
  71. controller: widget.controller ?? ScrollController(),
  72. children: children,
  73. );
  74. } else {
  75. return Column(
  76. mainAxisAlignment: MainAxisAlignment.center,
  77. mainAxisSize: MainAxisSize.min,
  78. children: children,
  79. );
  80. }
  81. }
  82. Widget _buildItemWidget(CheckBoxCellGroupItem<T> item) {
  83. final label = widget.labelGetter.call(item.data);
  84. final value = widget.valueGetter.call(item.data);
  85. final isChecked = _checkedValues.contains(value);
  86. return VCheckBoxCell<TValue>(
  87. label: label,
  88. value: value,
  89. isChecked: isChecked,
  90. isDisabled: item.isDisabled,
  91. onChanged: (_, isChecked) {
  92. _onCheckChanged(value, item.data, isChecked);
  93. },
  94. );
  95. }
  96. void _onCheckChanged(TValue value, T data, bool isChecked) {
  97. setState(() {
  98. if (isChecked) {
  99. if (_checkedValues.contains(value) == false) {
  100. _checkedValues.add(value);
  101. }
  102. } else {
  103. _checkedValues.remove(value);
  104. }
  105. widget.onChanged?.call(value, isChecked, data, _checkedValues);
  106. });
  107. }
  108. }