本文详细介绍如何在Flutter鸿蒙应用中实现倒计时和秒表功能,通过纯Dart实现跨平台定时器组件。

Flutter 三方库 cached_network_image 的鸿蒙化适配与实战指南
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

一、前言

定时器是移动应用中常见的功能组件,广泛应用于运动健身、烹饪计时、学习专注等场景。在Flutter鸿蒙开发中,我们可以利用Dart语言的Timer类实现高性能的定时器功能,无需依赖原生API,实现真正的跨平台一致性。

本文将介绍如何实现:

  • 倒计时功能(支持暂停、继续、停止)
  • 秒表功能(支持计时、暂停、重置)
  • 时间格式化显示

二、定时器核心实现

2.1 状态枚举定义

首先定义定时器的状态枚举:

enum TimerState {
  idle,      // 空闲状态
  running,   // 运行中
  paused,    // 已暂停
  finished,  // 已完成
}

2.2 倒计时实现

倒计时类使用Timer.periodic实现每秒触发:

class CountdownTimer {
  final int totalSeconds;
  int remainingSeconds;
  TimerState state = TimerState.idle;
  Timer? _timer;
  Function(int)? onTick;
  Function()? onFinish;

  CountdownTimer({
    required this.totalSeconds,
    this.onTick,
    this.onFinish,
  }) : remainingSeconds = totalSeconds;

  void start() {
    if (state == TimerState.running) return;
    state = TimerState.running;
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (remainingSeconds > 0) {
        remainingSeconds--;
        onTick?.call(remainingSeconds);
        if (remainingSeconds == 0) {
          stop();
          state = TimerState.finished;
          onFinish?.call();
        }
      }
    });
  }

  void pause() {
    if (state != TimerState.running) return;
    _timer?.cancel();
    state = TimerState.paused;
  }

  void resume() {
    if (state != TimerState.paused) return;
    start();
  }

  void stop() {
    _timer?.cancel();
    _timer = null;
    state = TimerState.idle;
  }

  void reset() {
    stop();
    remainingSeconds = totalSeconds;
    state = TimerState.idle;
  }

  void dispose() {
    stop();
  }
}

2.3 秒表实现

秒表类同样使用Timer.periodic,但逻辑更简单:

class StopwatchTimer {
  int elapsedSeconds = 0;
  TimerState state = TimerState.idle;
  Timer? _timer;
  Function(int)? onTick;

  void start() {
    if (state == TimerState.running) return;
    state = TimerState.running;
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      elapsedSeconds++;
      onTick?.call(elapsedSeconds);
    });
  }

  void pause() {
    if (state != TimerState.running) return;
    _timer?.cancel();
    state = TimerState.paused;
  }

  void resume() {
    if (state != TimerState.paused) return;
    start();
  }

  void reset() {
    _timer?.cancel();
    _timer = null;
    elapsedSeconds = 0;
    state = TimerState.idle;
  }

  void dispose() {
    _timer?.cancel();
    _timer = null;
  }

  String get formattedTime {
    final hours = elapsedSeconds ~/ 3600;
    final minutes = (elapsedSeconds % 3600) ~/ 60;
    final seconds = elapsedSeconds % 60;
    if (hours > 0) {
      return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
    }
    return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
  }
}

三、UI界面实现

3.1 倒计时界面

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

  
  State<TimerPage> createState() => _TimerPageState();
}

class _TimerPageState extends State<TimerPage> {
  CountdownTimer? _countdownTimer;
  int _countdownMinutes = 5;
  int _countdownSeconds = 0;

  void _startCountdown() {
    _countdownTimer?.dispose();
    final totalSeconds = _countdownMinutes * 60 + _countdownSeconds;
    if (totalSeconds <= 0) return;

    _countdownTimer = CountdownTimer(
      totalSeconds: totalSeconds,
      onTick: (_) => setState(() {}),
      onFinish: () {
        setState(() {});
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('倒计时结束!')),
        );
      },
    );
    _countdownTimer!.start();
    setState(() {});
  }

  
  Widget build(BuildContext context) {
    // 构建UI...
  }
}

3.2 时间选择器

使用DropdownButton实现分钟和秒数选择:

Row(
  children: [
    Expanded(
      child: Column(
        children: [
          const Text('分钟'),
          DropdownButton<int>(
            value: _countdownMinutes,
            isExpanded: true,
            items: List.generate(60, (i) => 
              DropdownMenuItem(value: i, child: Text('$i'))),
            onChanged: (v) => setState(() => _countdownMinutes = v ?? 0),
          ),
        ],
      ),
    ),
    const SizedBox(width: 16),
    Expanded(
      child: Column(
        children: [
          const Text('秒'),
          DropdownButton<int>(
            value: _countdownSeconds,
            isExpanded: true,
            items: List.generate(60, (i) => 
              DropdownMenuItem(value: i, child: Text('$i'))),
            onChanged: (v) => setState(() => _countdownSeconds = v ?? 0),
          ),
        ],
      ),
    ),
  ],
)

四、关键实现要点

4.1 资源释放

dispose方法中正确释放Timer资源:


void dispose() {
  _countdownTimer?.dispose();
  _stopwatchTimer?.dispose();
  super.dispose();
}

4.2 状态管理

使用setState触发UI更新,确保倒计时显示实时更新:

_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
  remainingSeconds--;
  onTick?.call(remainingSeconds);  // 触发setState
});

4.3 时间格式化

统一的时间格式化方法:

static String formatTime(int seconds) {
  final hours = seconds ~/ 3600;
  final minutes = (seconds % 3600) ~/ 60;
  final secs = seconds % 60;
  if (hours > 0) {
    return '${hours.toString().padLeft(2, '0')}:${minutes.toString().padLeft(2, '0')}:${secs.toString().padLeft(2, '0')}';
  }
  return '${minutes.toString().padLeft(2, '0')}:${secs.toString().padLeft(2, '0')}';
}

五、在鸿蒙平台运行

由于定时器功能完全由Dart实现,无需任何原生代码适配,可以直接在鸿蒙平台运行:

  1. 确保Flutter环境已配置鸿蒙支持
  2. 在DevEco Studio中打开项目
  3. 连接鸿蒙设备或模拟器
  4. 运行应用即可看到定时器功能
    在这里插入图片描述

六、扩展功能建议

可以进一步扩展的功能:

  1. 预设时间模板:添加常用时间快捷选择(1分钟、5分钟、10分钟等)
  2. 多计时器支持:同时运行多个倒计时
  3. 后台运行:结合原生API实现后台计时
  4. 提醒音效:倒计时结束时播放提示音
  5. 振动提醒:倒计时结束时触发振动

七、总结

本文介绍了如何在Flutter鸿蒙应用中实现定时器功能。通过纯Dart实现,我们获得了以下优势:

  • 跨平台一致性:无需针对不同平台编写原生代码
  • 代码简洁:利用Dart的Timer类实现核心逻辑
  • 易于维护:所有逻辑集中在Dart层
  • 性能优异:Dart的异步特性确保UI流畅

定时器是应用中常见的基础功能,合理设计可以提升用户体验。


本文为Flutter鸿蒙开发系列文章之一,更多实战内容请关注后续更新。

CSDN社区: https://bbs.csdn.net/forums/4f54ff014fbd4d42b72d3c5c1d3c5a4e

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐