You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 10:05:29