Flutter TimePicker如何设置双12小时环形显示?
解决方案
方法1:正确配置本地化实现12小时双环显示
默认的showTimePicker本身支持12小时制双环样式,问题可能出在你的本地化配置不完整。按以下步骤操作:
- 在
pubspec.yaml中添加依赖:
dependencies: flutter_localizations: sdk: flutter
- 在你的
MaterialApp中配置本地化支持:
import 'package:flutter_localizations/flutter_localizations.dart'; MaterialApp( localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], supportedLocales: const [ Locale('en', 'US'), // 12小时制地区 // 可添加其他需要的语言 ], locale: const Locale('en', 'US'), // 强制使用12小时制地区 // ...其他配置 )
- 调用
showTimePicker时指定locale(可选,若全局已配置可省略):
time = await showTimePicker( context: context, initialTime: TimeOfDay.fromDateTime(widget.notify.fireTime), locale: const Locale('en', 'US'), );
配置完成后,showTimePicker会自动切换为12小时双环(带AM/PM选择)的样式。
方法2:强制关闭24小时制快速切换样式
如果本地化配置后仍不生效,可通过自定义builder强制关闭24小时制显示逻辑:
time = await showTimePicker( context: context, initialTime: TimeOfDay.fromDateTime(widget.notify.fireTime), builder: (context, child) { return MediaQuery( data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: false), child: child!, ); }, );
这个方式无需依赖全局本地化配置,直接让TimePicker采用12小时双环显示。
方法3:自定义完整双环TimePicker组件
如果以上方法都不符合需求,可基于滚动轮组件实现完全自定义的双环小时选择器,示例如下(简化版):
// 自定义双环小时选择器对话框 Future<TimeOfDay?> showCustom12HourTimePicker(BuildContext context, TimeOfDay initialTime) { return showDialog<TimeOfDay>( context: context, builder: (context) { int selectedHour = initialTime.hour % 12; bool isAM = initialTime.hour < 12; int selectedMinute = initialTime.minute; return AlertDialog( title: const Text('选择时间'), content: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ // 小时选择环(1-12) SizedBox( width: 80, height: 150, child: ListWheelScrollView.useDelegate( itemExtent: 40, perspective: 0.005, onSelectedItemChanged: (index) { selectedHour = index + 1; }, childDelegate: ListWheelChildBuilderDelegate( builder: (context, index) => Center( child: Text('${index + 1}'), ), childCount: 12, ), ), ), // AM/PM选择环 SizedBox( width: 80, height: 150, child: ListWheelScrollView.useDelegate( itemExtent: 40, perspective: 0.005, onSelectedItemChanged: (index) { isAM = index == 0; }, childDelegate: ListWheelChildBuilderDelegate( builder: (context, index) => Center( child: Text(index == 0 ? 'AM' : 'PM'), ), childCount: 2, ), ), ), // 分钟选择环 SizedBox( width: 80, height: 150, child: ListWheelScrollView.useDelegate( itemExtent: 40, perspective: 0.005, onSelectedItemChanged: (index) { selectedMinute = index; }, childDelegate: ListWheelChildBuilderDelegate( builder: (context, index) => Center( child: Text('${index.toString().padLeft(2, '0')}'), ), childCount: 60, ), ), ), ], ), ], ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), TextButton( onPressed: () { int finalHour = selectedHour + (isAM ? 0 : 12); Navigator.pop(context, TimeOfDay(hour: finalHour, minute: selectedMinute)); }, child: const Text('确认'), ), ], ); }, ); }
使用时直接调用该方法:
time = await showCustom12HourTimePicker(context, TimeOfDay.fromDateTime(widget.notify.fireTime));
内容的提问来源于stack exchange,提问作者Erik0806
相关产品推荐
相关产品推荐

