123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- import 'package:flutter/material.dart';
- import 'package:get/get.dart';
- import 'alert_dialog.dart';
- class VSelectModel {
- VSelectModel({required this.name, required this.code});
- final String name;
- final String code;
- }
- class VDialogSelect<T, TValue> extends StatelessWidget {
- /// 数据集
- final List<T> source;
- /// 初始值
- final TValue? initialValue;
- /// 弹窗标题
- final String? title;
- /// 选项文本提取函数
- final String Function(T data)? labelGetter;
- /// 选项外显组件构建器
- final Widget Function(T data)? labelBuilder;
- /// 选项值提取函数
- final TValue Function(T data) valueGetter;
- const VDialogSelect({
- super.key,
- required this.source,
- this.title,
- this.initialValue,
- this.labelGetter,
- this.labelBuilder,
- required this.valueGetter,
- }) : assert(labelGetter != null || labelBuilder != null);
- Future<T?> show<T>() => VAlertDialog.showDialog<T>(this);
- @override
- Widget build(BuildContext context) {
- return VAlertDialog(
- width: 460,
- title: title,
- content: Scrollbar(
- thumbVisibility: true,
- child: SingleChildScrollView(
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: _buildOptions(context),
- ),
- ),
- ),
- showCancel: true,
- );
- }
- List<Widget> _buildOptions(BuildContext context) {
- final primaryColor = Theme.of(context).primaryColor;
- final children = <Widget>[];
- for (var i = 0; i < source.length; i++) {
- final data = source[i];
- final val = valueGetter(data);
- final isSelected = initialValue == val;
- Widget label;
- if (labelBuilder != null) {
- label = labelBuilder!(data);
- } else {
- label = Text(
- labelGetter!(data),
- style: TextStyle(
- color: isSelected ? primaryColor : Colors.black,
- fontSize: 20,
- ),
- );
- }
- final widget = Container(
- alignment: Alignment.centerLeft,
- height: 56,
- padding: const EdgeInsets.symmetric(horizontal: 8),
- color: isSelected ? Theme.of(context).secondaryHeaderColor : null,
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Row(
- mainAxisSize: MainAxisSize.min,
- children: [const SizedBox(width: 20), label],
- ),
- if (isSelected)
- Row(
- children: [
- Icon(
- Icons.check,
- size: 24,
- color: primaryColor,
- ),
- const SizedBox(width: 20)
- ],
- ),
- ],
- ),
- );
- children.add(
- Material(
- color: Colors.transparent,
- child: Ink(
- child: InkWell(
- onTap: () {
- _onSelected(val);
- },
- child: widget,
- ),
- ),
- ),
- );
- }
- return children;
- }
- void _onSelected(TValue value) {
- Get.back(result: value);
- }
- }
|