84 lines
2.5 KiB
Dart
84 lines
2.5 KiB
Dart
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter/cupertino.dart';
|
||
|
|
||
|
/// 通用底部弹窗选择器
|
||
|
/// Example:
|
||
|
/// ```dart
|
||
|
/// final choice = await BottomPicker.show<String>(
|
||
|
/// context,
|
||
|
/// items: ['选项1', '选项2', '选项3'],
|
||
|
/// itemBuilder: (item) => Text(item, textAlign: TextAlign.center),
|
||
|
/// initialIndex: 1,
|
||
|
/// );
|
||
|
/// if (choice != null) {
|
||
|
/// // 用户点击确定并选择了 choice
|
||
|
/// }
|
||
|
/// ```
|
||
|
class BottomPicker {
|
||
|
/// 显示底部选择器弹窗
|
||
|
///
|
||
|
/// [items]: 选项列表
|
||
|
/// [itemBuilder]: 每个选项的展示 Widget
|
||
|
/// [initialIndex]: 初始选中索引
|
||
|
/// [itemExtent]: 列表行高
|
||
|
/// [height]: 弹窗总高度
|
||
|
static Future<T?> show<T>(
|
||
|
BuildContext context, {
|
||
|
required List<T> items,
|
||
|
required Widget Function(T item) itemBuilder,
|
||
|
int initialIndex = 0,
|
||
|
double itemExtent = 40.0,
|
||
|
double height = 250,
|
||
|
}) {
|
||
|
// 当前选中项
|
||
|
T selected = items[initialIndex];
|
||
|
|
||
|
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(
|
||
|
onPressed: () => Navigator.of(ctx).pop(selected),
|
||
|
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(),
|
||
|
),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
);
|
||
|
},
|
||
|
);
|
||
|
}
|
||
|
}
|