import 'package:flutter/material.dart'; import 'package:lszlgl/base/base_lifecycle_state.dart'; import 'package:lszlgl/widget/button.dart'; import '../config/colors.dart'; import 'card_item.dart'; /// 弹出菜单选项弹框 /// * [list] 选项列表数据源 /// * [title] 标题 /// * [multiple] 多选,默认单选 /// * [selectCountMax] 最大选择数量 /// * [backgroundColor] 背景颜色 /// * [borderRadius] 圆角 /// * [constraints] 尺寸约束 /// * [isScrollControlled] 高度自适应, 默认true /// * [isDismissible] 点击空白处关闭 /// * [enableDrag] 拖动关闭 Future showMenuDialog( List? list, { String? title, bool multiple = false, int? selectCountMax, Color? backgroundColor = Colors.white, BorderRadiusGeometry? borderRadius, BoxConstraints? constraints, bool isScrollControlled = true, bool isDismissible = true, bool enableDrag = true, }) { return showModalBottomSheet( context: MyNavigator.navigator.currentState!.context, constraints: constraints, isScrollControlled: isScrollControlled, isDismissible: isDismissible, enableDrag: enableDrag, useSafeArea: true, builder: (_) => MenuDialog( list: list, title: title, multiple: multiple, selectCountMax: selectCountMax, backgroundColor: backgroundColor, ), ); } class MenuDialog extends StatelessWidget { final List list; final String? title; final bool multiple; final int? selectCountMax; final Color? backgroundColor; final BorderRadiusGeometry? borderRadius; final ValueNotifier selectCount; MenuDialog({ super.key, List? list, this.title, required this.multiple, this.selectCountMax, this.backgroundColor, this.borderRadius, }) : list = list ?? [], selectCount = (list ?? []).where((e) => e.select).length.notifier(); void onEnterClick() { if (list.isEmpty) return; List selectList = list.where((item) => item.select).toList(); MyNavigator.pop(selectList); } @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: backgroundColor, borderRadius: borderRadius ?? const BorderRadius.only(topLeft: Radius.circular(16), topRight: Radius.circular(16)), ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ buildTitle(), buildList(), buildButton(), const SizedBox(width: double.infinity, height: 24), ], ), ); } Widget buildTitle() { return Padding( padding: const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24), child: Row( children: [ Expanded( child: Text( '请选择${title ?? ''}:', style: const TextStyle(color: Color(0xFF333333), fontSize: 16, fontWeight: FontWeight.w500), ), ), MyButton('关闭', alignment: null, onTap: () => MyNavigator.pop()), ], ), ); } Widget buildList() { if (list.isEmpty) { return Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(vertical: 24), child: const Text( '没有选项数据', style: TextStyle(fontSize: 16, color: MyColor.c_666666), ), ); } return Flexible( child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: List.generate(list.length, buildItem).toList(), ), ), ); } Widget buildItem(int index) { var item = list[index]; return StatefulBuilder(builder: (_, setState) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { if (multiple) { if (!item.select && selectCountMax != null && selectCountMax == selectCount.value) { MyNavigator.showToast('选中不能超过$selectCountMax个'); return; } item.select = !item.select; setState(() {}); } else { // 取消之前选择 for (var value in list) { if (value.select) { value.select = false; break; } } // 选中当前项 item.select = true; onEnterClick(); } }, child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), alignment: Alignment.center, color: Colors.white, child: Text( item.name ?? '', style: TextStyle( color: item.select ? const Color(0xFF01B2C8) : MyColor.c_666666, fontSize: 14, fontWeight: FontWeight.w500, ), ), ), index < list.length - 1 ? const Divider( color: Color(0xFFF3F3F3), height: 0, thickness: 1, indent: 16, endIndent: 16, ) : const SizedBox.shrink(), ], ), ); }); } Widget buildButton() { if (!multiple || list.isEmpty) return const SizedBox.shrink(); return Padding( padding: const EdgeInsets.only(top: 16), child: Row( children: [ const Spacer(), Expanded(flex: 2, child: MyButton('确认', onTap: onEnterClick)), const Spacer(), ], ), ); } }