import 'package:animate_do/animate_do.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import '../../app/core/themes/theme.dart'; import '../../app/global_widgets/global_widgets.dart'; import 'multi_select_action.dart'; import 'multi_select_item.dart'; /// A bottom sheet widget containing either a classic checkbox style list, or a chip style list. class MultiSelectBottomSheet extends StatefulWidget with MultiSelectActions { /// List of items to select from. final List> items; /// The list of selected values before interaction. final List initialValue; /// The text at the top of the BottomSheet. final String title; /// Fires when the an item is selected / unselected. final void Function(List)? onSelectionChanged; /// Fires when confirm is tapped. final void Function(List)? onConfirm; /// Fires when clear is tapped. final void Function(List)? onClear; /// Moves the selected items to the top of the list. final bool separateSelectedItems; MultiSelectBottomSheet({ required this.items, required this.initialValue, required this.title, this.onSelectionChanged, this.onConfirm, this.onClear, this.separateSelectedItems = false, }); @override _MultiSelectBottomSheetState createState() => _MultiSelectBottomSheetState(items); } class _MultiSelectBottomSheetState extends State> { List _selectedValues = []; List> _items; _MultiSelectBottomSheetState(this._items); void _clearFilter() { for (int i = 0; i < _items.length; i++) { if (_selectedValues.contains(_items[i].value)) { _items[i].selected = false; } } _selectedValues.clear(); widget.onClearTap(context, _selectedValues, widget.onClear); setState(() {}); } @override void initState() { super.initState(); _selectedValues.addAll(widget.initialValue); for (int i = 0; i < _items.length; i++) { if (_selectedValues.contains(_items[i].value)) { _items[i].selected = true; } } if (widget.separateSelectedItems) { _items = widget.separateSelected(_items); } } /// Returns a CheckboxListTile Widget _buildListItem(MultiSelectItem item) { final theme = Theme.of(context); final oldCheckboxTheme = theme.checkboxTheme; final newCheckBoxTheme = oldCheckboxTheme.copyWith( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(300)), ); return Theme( data: theme.copyWith(checkboxTheme: newCheckBoxTheme), child: Transform.translate( offset: Offset(-24, 0), child: Transform.scale( scale: 1.h, child: CheckboxListTile( checkColor: ThemeColor.white, value: item.selected, activeColor: ThemeColor.mainColor, title: Text( item.label, ), controlAffinity: ListTileControlAffinity.leading, onChanged: (checked) { setState(() { _selectedValues = widget.onItemCheckedChange(_selectedValues, item.value, checked!); if (checked) { item.selected = true; } else { item.selected = false; } if (widget.separateSelectedItems) { _items = widget.separateSelected(_items); } }); if (widget.onSelectionChanged != null) { widget.onSelectionChanged!(_selectedValues); } }, ), ), ), ); } @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: BottomSheetScaffold( title: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(widget.title, style: AppTheme.bottomSheetHeaderStyle), SizedBox(height: 16), // search box Container( padding: const EdgeInsets.all(8), height: 40.h, width: double.infinity, decoration: new BoxDecoration( color: ThemeColor.colorEFF0F4, borderRadius: BorderRadius.circular(8), ), child: TextFormField( cursorColor: Colors.black, inputFormatters: [new LengthLimitingTextInputFormatter(30)], decoration: InputDecoration( border: InputBorder.none, prefixIcon: Icon( Icons.search, size: 24.h, color: Colors.grey, ), ), onChanged: (val) { List> filteredList = []; filteredList = widget.updateSearchQuery(val, widget.items); setState(() { if (widget.separateSelectedItems) { _items = widget.separateSelected(filteredList); } else { _items = filteredList; } }); }, ), ), SizedBox(height: 20), Row( children: [ Text( 'applied'.tr, style: new TextStyle( color: ThemeColor.color717278, fontSize: 16.sp, ), ), Spacer(), _selectedValues.isNotEmpty ? FadeIn( child: TextButton( child: Text('clear'.tr), style: TextButton.styleFrom(foregroundColor: ThemeColor.mainColor), onPressed: () { debugPrint('Clear Pressed'); _clearFilter(); }, ), ) : SizedBox.shrink(), ], ), ], ), body: AnimatedSize( duration: Duration(milliseconds: 1300), curve: Curves.fastLinearToSlowEaseIn, child: ConstrainedBox( constraints: new BoxConstraints(minHeight: 0.3.sh), child: SingleChildScrollView( child: Column( children: _items.map((item) => _buildListItem(item)).toList(), ), ), ), ), footer: _selectedValues.isNotEmpty ? FadeIn( duration: Duration(milliseconds: 900), child: ColoredButton( title: 'done'.tr, btnColor: ThemeColor.mainColor, callback: () { widget.onConfirmTap(context, _selectedValues, widget.onConfirm); }, ), ) : SizedBox.shrink(), ), ); } }