| 
									
										
										
										
											2025-07-25 18:06:37 +08:00
										 |  |  | import 'package:flutter/material.dart'; | 
					
						
							|  |  |  | import 'package:flutter/cupertino.dart'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /// 通用底部弹窗选择器
 | 
					
						
							|  |  |  | /// Example:
 | 
					
						
							|  |  |  | /// ```dart
 | 
					
						
							|  |  |  | /// final choice = await BottomPickerTwo.show<String>(
 | 
					
						
							|  |  |  | ///   context,
 | 
					
						
							|  |  |  | ///   items: ['选项1', '选项2', '选项3'],
 | 
					
						
							|  |  |  | ///   itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
 | 
					
						
							|  |  |  | ///   initialIndex: 1,
 | 
					
						
							|  |  |  | /// );
 | 
					
						
							|  |  |  | /// if (choice != null) {
 | 
					
						
							|  |  |  | ///   // 用户点击确定并选择了 choice
 | 
					
						
							|  |  |  | /// }
 | 
					
						
							|  |  |  | /// ```
 | 
					
						
							|  |  |  | class BottomPickerTwo { | 
					
						
							|  |  |  |   /// 显示底部选择器弹窗
 | 
					
						
							|  |  |  |   ///
 | 
					
						
							|  |  |  |   /// [items]: 选项列表
 | 
					
						
							|  |  |  |   /// [itemBuilder]: 每个选项的展示 Widget
 | 
					
						
							|  |  |  |   /// [initialIndex]: 初始选中索引
 | 
					
						
							|  |  |  |   /// [itemExtent]: 列表行高
 | 
					
						
							|  |  |  |   /// [height]: 弹窗总高度
 | 
					
						
							|  |  |  |   static Future<dynamic> show<T>( | 
					
						
							|  |  |  |       BuildContext context, { | 
					
						
							|  |  |  |         required List<dynamic> items, | 
					
						
							|  |  |  |         required Widget Function(dynamic item) itemBuilder, | 
					
						
							|  |  |  |         int initialIndex = 0, | 
					
						
							|  |  |  |         double itemExtent = 40.0, | 
					
						
							|  |  |  |         double height = 250, | 
					
						
							|  |  |  |       }) { | 
					
						
							|  |  |  |     // 当前选中项
 | 
					
						
							| 
									
										
										
										
											2025-07-29 08:53:00 +08:00
										 |  |  |     dynamic selected = items[initialIndex]; | 
					
						
							| 
									
										
										
										
											2025-07-25 18:06:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return showModalBottomSheet<T>( | 
					
						
							|  |  |  |       context: context, | 
					
						
							|  |  |  |       backgroundColor: Colors.white, | 
					
						
							|  |  |  |       shape: const RoundedRectangleBorder( | 
					
						
							|  |  |  |         borderRadius: BorderRadius.vertical(top: Radius.circular(12)), | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |       builder: (ctx) { | 
					
						
							|  |  |  |         return SizedBox( | 
					
						
							|  |  |  |           height: height, | 
					
						
							|  |  |  |           child: Column( | 
					
						
							|  |  |  |             children: [ | 
					
						
							|  |  |  |               // 按钮行
 | 
					
						
							|  |  |  |               Padding( | 
					
						
							|  |  |  |                 padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), | 
					
						
							|  |  |  |                 child: Row( | 
					
						
							|  |  |  |                   mainAxisAlignment: MainAxisAlignment.spaceBetween, | 
					
						
							|  |  |  |                   children: [ | 
					
						
							|  |  |  |                     TextButton( | 
					
						
							|  |  |  |                       onPressed: () => Navigator.of(ctx).pop(), | 
					
						
							|  |  |  |                       child: const Text('取消'), | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                     TextButton( | 
					
						
							| 
									
										
										
										
											2025-07-29 08:53:00 +08:00
										 |  |  |                       onPressed: () => Navigator.of(ctx).pop(selected["NAME"]), | 
					
						
							| 
									
										
										
										
											2025-07-25 18:06:37 +08:00
										 |  |  |                       child: const Text('确定'), | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                   ], | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |               const Divider(height: 1), | 
					
						
							|  |  |  |               // 滚动选择器
 | 
					
						
							|  |  |  |               Expanded( | 
					
						
							|  |  |  |                 child: CupertinoPicker( | 
					
						
							|  |  |  |                   scrollController: | 
					
						
							|  |  |  |                   FixedExtentScrollController(initialItem: initialIndex), | 
					
						
							|  |  |  |                   itemExtent: 30, | 
					
						
							|  |  |  |                   onSelectedItemChanged: (index) { | 
					
						
							|  |  |  |                     selected = items[index]; | 
					
						
							|  |  |  |                   }, | 
					
						
							|  |  |  |                   children: items.map(itemBuilder).toList(), | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |               ), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |           ), | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |