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

Flutter中如何创建支持选择天、时、分的AlertDialog?

实现带滚动选择器的定时器弹窗

下面是适合新手的实现方案,用Flutter官方组件构建符合需求的滚动选择弹窗,无需依赖第三方包:

核心思路

用AlertDialog作为弹窗容器,内部嵌套三个CupertinoPicker分别处理天、时、分的滚动选择,同时通过状态管理控制选择范围的最大值限制(6天23小时59分),固定弹窗和选择器尺寸避免空间占用过大。

完整代码示例

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class TimerPickerDialog extends StatefulWidget {
  const TimerPickerDialog({super.key});

  @override
  State<TimerPickerDialog> createState() => _TimerPickerDialogState();
}

class _TimerPickerDialogState extends State<TimerPickerDialog> {
  // 初始选中值
  int _selectedDays = 0;
  int _selectedHours = 0;
  int _selectedMinutes = 0;

  // 生成各选择器的可选范围
  List<int> get _dayOptions => List.generate(7, (index) => index); // 0-6天
  List<int> get _hourOptions => List.generate(24, (index) => index); // 0-23时
  List<int> get _minuteOptions => List.generate(60, (index) => index); // 0-59分

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: const Text('设置定时器'),
      content: SizedBox(
        height: 180, // 固定弹窗高度避免过度占用屏幕
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            // 天选择器
            _buildPicker(
              options: _dayOptions,
              selectedValue: _selectedDays,
              onSelectedItemChanged: (index) {
                setState(() {
                  _selectedDays = _dayOptions[index];
                  // 当天数设为6时,若小时超过23则重置为23
                  if (_selectedDays == 6 && _selectedHours > 23) {
                    _selectedHours = 23;
                  }
                  // 6天23小时时,若分钟超过59则重置为59
                  if (_selectedDays == 6 && _selectedHours == 23 && _selectedMinutes > 59) {
                    _selectedMinutes = 59;
                  }
                });
              },
              label: '天',
            ),
            // 小时选择器
            _buildPicker(
              options: _hourOptions,
              selectedValue: _selectedHours,
              onSelectedItemChanged: (index) {
                setState(() {
                  _selectedHours = _hourOptions[index];
                  // 6天23小时时,若分钟超过59则重置为59
                  if (_selectedDays == 6 && _selectedHours == 23 && _selectedMinutes > 59) {
                    _selectedMinutes = 59;
                  }
                });
              },
              label: '时',
            ),
            // 分钟选择器
            _buildPicker(
              options: _minuteOptions,
              selectedValue: _selectedMinutes,
              onSelectedItemChanged: (index) {
                setState(() {
                  _selectedMinutes = _minuteOptions[index];
                });
              },
              label: '分',
            ),
          ],
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('取消'),
        ),
        TextButton(
          onPressed: () {
            // 返回选中结果,可替换为你的业务逻辑
            Navigator.pop(context, {
              'days': _selectedDays,
              'hours': _selectedHours,
              'minutes': _selectedMinutes,
            });
          },
          child: const Text('确认'),
        ),
      ],
    );
  }

  // 封装通用选择器组件,减少重复代码
  Widget _buildPicker({
    required List<int> options,
    required int selectedValue,
    required ValueChanged<int> onSelectedItemChanged,
    required String label,
  }) {
    return Column(
      children: [
        Text(label),
        const SizedBox(height: 8),
        SizedBox(
          width: 60, // 固定选择器宽度避免布局混乱
          child: CupertinoPicker(
            magnification: 1.2,
            squeeze: 1.2,
            useMagnifier: true,
            itemExtent: 32, // 单个选项的高度
            scrollController: FixedExtentScrollController(
              initialItem: options.indexOf(selectedValue),
            ),
            onSelectedItemChanged: onSelectedItemChanged,
            children: options.map((value) {
              return Center(
                child: Text(
                  '$value',
                  style: const TextStyle(fontSize: 16),
                ),
              );
            }).toList(),
          ),
        ),
      ],
    );
  }
}

// 弹窗调用示例,可直接在按钮点击事件中使用
void showTimerPicker(BuildContext context) {
  showDialog(
    context: context,
    builder: (context) => const TimerPickerDialog(),
  ).then((result) {
    if (result != null) {
      // 处理选中结果,比如更新页面状态或打印
      print('选中:${result['days']}天 ${result['hours']}时 ${result['minutes']}分');
    }
  });
}

关键说明

  • 用CupertinoPicker实现你需要的滚动选择样式,适配Material风格弹窗
  • 固定弹窗和选择器的尺寸,彻底解决DropdownBox弹窗过大的问题
  • 通过状态联动实现最大值限制:当选中6天时,自动修正小时和分钟不超过23和59
  • 封装的_buildPicker方法简化了代码结构,新手易读易改
  • 调用示例中的showTimerPicker函数可直接嵌入按钮点击事件,快速启用功能

内容的提问来源于stack exchange,提问作者AKC

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 00:47:38