123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- import 'package:flutter/material.dart';
- /// 按钮式多选框组
- class VCheckBoxButtonGroup<T, TValue> extends StatefulWidget {
- final List<T> source;
- final List<TValue>? values;
- final String Function(T data) labelGetter;
- final TValue Function(T data) valueGetter;
- final ValueChanged<List<TValue>>? onChanged;
- final double? itemWidth;
- const VCheckBoxButtonGroup({
- super.key,
- required this.source,
- this.values,
- required this.labelGetter,
- required this.valueGetter,
- this.onChanged,
- this.itemWidth,
- });
- @override
- State<StatefulWidget> createState() => _VCheckBoxGroupState<T, TValue>();
- }
- class _VCheckBoxGroupState<T, TValue>
- extends State<VCheckBoxButtonGroup<T, TValue>> {
- late List<TValue> _checkedValues;
- @override
- void initState() {
- if (widget.values != null) {
- _checkedValues = List.from(widget.values!);
- } else {
- _checkedValues = [];
- }
- super.initState();
- }
- @override
- Widget build(BuildContext context) {
- final children = <Widget>[];
- final length = widget.source.length;
- for (var i = 0; i < length; i++) {
- final e = widget.source[i];
- final value = widget.valueGetter(e);
- final isChecked = _checkedValues.contains(value);
- // children.add(
- // SizedBox(
- // width: widget.itemWidth ?? 160,
- // child: VCheckBoxButton(
- // label: widget.labelGetter(e),
- // isChecked: isChecked,
- // onChanged: (status) {
- // _onItemChanged(value, status);
- // },
- // ),
- // ),
- // );
- // TODO:
- children.add(
- VCheckBoxButton(
- label: widget.labelGetter(e),
- isChecked: isChecked,
- onChanged: (status) {
- _onItemChanged(value, status);
- },
- ),
- );
- }
- return Wrap(
- spacing: 12,
- runSpacing: 8,
- children: children,
- );
- }
- void _onItemChanged(TValue value, bool isChecked) {
- if (isChecked) {
- if (_checkedValues.contains(value) == false) {
- _checkedValues.add(value);
- }
- } else {
- _checkedValues.remove(value);
- }
- widget.onChanged?.call(_checkedValues);
- }
- }
- /// 按钮式多选框
- class VCheckBoxButton extends StatefulWidget {
- /// 文本
- final String label;
- /// 是否默认选中
- final bool? isChecked;
- /// 选中状态变更
- final ValueChanged<bool>? onChanged;
- const VCheckBoxButton({
- super.key,
- required this.label,
- this.isChecked,
- this.onChanged,
- });
- @override
- State<StatefulWidget> createState() => _VCheckBoxState();
- }
- class _VCheckBoxState extends State<VCheckBoxButton> {
- bool _isChecked = false;
- @override
- void initState() {
- if (widget.isChecked != null) {
- _isChecked = widget.isChecked!;
- }
- super.initState();
- }
- @override
- Widget build(BuildContext context) {
- const height = 56.0;
- const borderRadius = height / 2;
- final primaryColor = Theme.of(context).primaryColor;
- return Material(
- child: Ink(
- child: InkWell(
- borderRadius: BorderRadius.circular(borderRadius),
- onTap: () {
- setState(() {
- _isChecked = !_isChecked;
- widget.onChanged?.call(_isChecked);
- });
- },
- child: Container(
- padding: const EdgeInsets.only(left: 0, right: borderRadius),
- alignment: Alignment.center,
- height: height,
- // constraints: const BoxConstraints(minWidth: 160),
- decoration: BoxDecoration(
- color: _isChecked ? primaryColor : Colors.white,
- borderRadius: BorderRadius.circular(borderRadius),
- border: _isChecked ? null : Border.all(color: primaryColor),
- ),
- child: Row(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- if (_isChecked) ...[
- const Icon(
- Icons.check_rounded,
- color: Colors.green,
- size: 24,
- ),
- const SizedBox(width: 8),
- ],
- if (!_isChecked) const SizedBox(width: 32),
- Text(
- widget.label,
- style: TextStyle(
- color: _isChecked ? Colors.white : primaryColor,
- fontSize: 20,
- ),
- ),
- ],
- ),
- ),
- ),
- ),
- );
- }
- }
|