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

Flutter中如何创建计时器选择器?能否实现iOS风格时长计时器?

Hey,这两个需求我刚好在Flutter项目里折腾过,给你详细说说,附完整的可运行代码示例~

一、创建通用计时器选择器(Material风格)

如果想要Material设计风格的计时器选择器,我们可以通过组合基础组件+底部弹窗来实现,核心是让用户直观选择分钟和秒数。我这里用DropdownButton做选择控件,配合showModalBottomSheet弹出选择界面:

import 'package:flutter/material.dart';

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

  @override
  State<TimerPickerDemo> createState() => _TimerPickerDemoState();
}

class _TimerPickerDemoState extends State<TimerPickerDemo> {
  // 存储选中的时长(单位:秒)
  int _selectedDuration = 0;

  // 生成0-60分钟的选项
  List<DropdownMenuItem<int>> get _minuteOptions {
    return List.generate(61, (index) => DropdownMenuItem(
      value: index * 60,
      child: Text('${index}分钟'),
    ));
  }

  // 生成0-59秒的选项
  List<DropdownMenuItem<int>> get _secondOptions {
    return List.generate(60, (index) => DropdownMenuItem(
      value: index,
      child: Text('${index}秒'),
    ));
  }

  void _showTimerPicker() {
    // 初始化临时变量,保存当前选中的分秒
    int tempMin = _selectedDuration ~/ 60;
    int tempSec = _selectedDuration % 60;

    showModalBottomSheet(
      context: context,
      builder: (context) => Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                DropdownButton<int>(
                  value: tempMin * 60,
                  items: _minuteOptions,
                  onChanged: (value) {
                    if (value != null) {
                      tempMin = value ~/ 60;
                      setState(() {
                        _selectedDuration = tempMin * 60 + tempSec;
                      });
                    }
                  },
                ),
                const Text('+'),
                DropdownButton<int>(
                  value: tempSec,
                  items: _secondOptions,
                  onChanged: (value) {
                    if (value != null) {
                      tempSec = value;
                      setState(() {
                        _selectedDuration = tempMin * 60 + tempSec;
                      });
                    }
                  },
                ),
              ],
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('确认'),
            )
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Material风格计时器选择器')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '选中时长:${_selectedDuration ~/ 60}分${_selectedDuration % 60}秒',
              style: const TextStyle(fontSize: 18),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _showTimerPicker,
              child: const Text('选择时长'),
            )
          ],
        ),
      ),
    );
  }
}

这个示例里,用户点击按钮会弹出底部选择框,通过下拉菜单选择分钟和秒数,选中后实时更新页面显示的时长。

二、实现iOS风格的时长计时器

当然可以!Flutter的Cupertino组件库自带了CupertinoTimerPicker,完全还原iOS原生的时长选择器样式和交互,支持设置显示时/分/秒的组合,非常好用。我给你写个完整的示例:

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

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

  @override
  State<IOStyleTimerPicker> createState() => _IOStyleTimerPickerState();
}

class _IOStyleTimerPickerState extends State<IOStyleTimerPicker> {
  Duration _selectedDuration = Duration.zero;

  void _showIOSPicker() {
    showCupertinoModalPopup(
      context: context,
      builder: (context) => Container(
        height: 300,
        color: CupertinoColors.white,
        child: Column(
          children: [
            // 顶部操作栏(取消/确认按钮)
            Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                CupertinoButton(
                  onPressed: () => Navigator.pop(context),
                  child: const Text('取消'),
                ),
                CupertinoButton(
                  onPressed: () {
                    Navigator.pop(context);
                    setState(() {}); // 确认后更新页面显示
                  },
                  child: const Text('确认'),
                ),
              ],
            ),
            // iOS风格核心选择器
            Expanded(
              child: CupertinoTimerPicker(
                // 控制显示的时间单位:hms=时分秒,ms=分秒,h=小时(按需选择)
                mode: CupertinoTimerPickerMode.hms,
                initialTimerDuration: _selectedDuration,
                // 实时监听时长变化
                onTimerDurationChanged: (newDuration) {
                  setState(() {
                    _selectedDuration = newDuration;
                  });
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('iOS风格时长计时器')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '选中时长:${_selectedDuration.inHours}时${_selectedDuration.inMinutes.remainder(60)}分${_selectedDuration.inSeconds.remainder(60)}秒',
              style: const TextStyle(fontSize: 18),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: _showIOSPicker,
              child: const Text('打开iOS风格选择器'),
            )
          ],
        ),
      ),
    );
  }
}

关键参数说明:

  • mode:控制选择器显示的时间单位,可选CupertinoTimerPickerMode.hms(时分秒)、CupertinoTimerPickerMode.ms(分秒)、CupertinoTimerPickerMode.h(仅小时);
  • initialTimerDuration:设置选择器的初始时长;
  • onTimerDurationChanged:实时获取用户选中的时长,用来更新状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:42:54