123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- 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<T?> showMenuDialog<T>(
- List<CardMenuData>? 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<CardMenuData> list;
- final String? title;
- final bool multiple;
- final int? selectCountMax;
- final Color? backgroundColor;
- final BorderRadiusGeometry? borderRadius;
- final ValueNotifier<int> selectCount;
- MenuDialog({
- super.key,
- List<CardMenuData>? list,
- this.title,
- required this.multiple,
- this.selectCountMax,
- this.backgroundColor,
- this.borderRadius,
- }) : list = list ?? [],
- selectCount = (list ?? []).where((e) => e.select).length.notifier<int>();
- void onEnterClick() {
- if (list.isEmpty) return;
- List<CardMenuData> 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(),
- ],
- ),
- );
- }
- }
|