番茄时间管理:鸿蒙Flutter 实现的高效时间管理工具

欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net




1. 项目介绍

在快节奏的现代生活中,高效的时间管理变得越来越重要。番茄工作法(Pomodoro Technique)作为一种流行的时间管理方法,通过将工作时间分解为25分钟的工作段和5分钟的休息段,帮助人们提高专注力和工作效率。本文将详细介绍如何使用 Flutter 实现一个功能完整的番茄时间管理应用,包括倒计时功能、任务管理、统计分析和自定义设置。

1.1 项目目标

  • 实现一个功能完整的番茄时间管理应用
  • 支持标准的番茄工作法时间设置
  • 提供任务管理功能,帮助用户跟踪待办事项
  • 实现统计功能,展示用户的工作和休息时间
  • 支持自定义时间设置,适应不同用户的需求
  • 确保在不同平台上的一致性表现

1.2 技术栈

  • Flutter:跨平台 UI 框架
  • Dart:编程语言
  • Timer:用于实现倒计时功能
  • StatefulWidget:用于管理应用状态
  • AnimatedContainer:用于实现平滑过渡效果
  • TextField:用于任务输入
  • ListView:用于任务列表展示

2. 核心功能设计

2.1 番茄钟功能

  • 工作时间:默认25分钟,可自定义
  • 短休息:默认5分钟,可自定义
  • 长休息:默认15分钟,可自定义
  • 自动循环:每4个番茄后自动进入长休息
  • 状态管理:工作、短休息、长休息、暂停、停止

2.2 任务管理

  • 添加任务:通过文本输入添加待办事项
  • 删除任务:支持删除已添加的任务
  • 任务列表:以列表形式展示所有任务

2.3 统计功能

  • 完成的番茄数:记录用户完成的番茄数量
  • 工作时间:计算总工作时间
  • 休息时间:计算总休息时间

2.4 设置功能

  • 工作时间调整:可调整工作时间(5-60分钟)
  • 短休息时间调整:可调整短休息时间(1-10分钟)
  • 长休息时间调整:可调整长休息时间(5-30分钟)

3. 技术架构

3.1 项目结构

复制代码
lib/
└── main.dart          # 主应用文件,包含所有代码

3.2 组件结构

复制代码
PomodoroApp
└── PomodoroScreen
    ├── State management (currentState, remainingTime, completedPomodoros, etc.)
    ├── Timer functionality (start, pause, stop, complete)
    ├── Task management (add, remove)
    ├── UI components
    │   ├── Timer display
    │   ├── Control buttons
    │   ├── Statistics section
    │   ├── Task management section
    │   └── Settings section
    └── Settings (workDuration, shortBreakDuration, longBreakDuration)

4. 关键代码解析

4.1 状态管理

dart 复制代码
enum TimerState {
  work,
  shortBreak,
  longBreak,
  paused,
  stopped,
}

class _PomodoroScreenState extends State<PomodoroScreen> {
  TimerState _currentState = TimerState.stopped;
  int _workDuration = 25 * 60; // 25分钟
  int _shortBreakDuration = 5 * 60; // 5分钟
  int _longBreakDuration = 15 * 60; // 15分钟
  int _remainingTime = 25 * 60;
  int _completedPomodoros = 0;
  int _currentCycle = 0;
  Timer? _timer;
  List<String> _tasks = [];
  String _newTask = '';
  // ...
}

代码解析

  • TimerState 枚举:定义了计时器的不同状态
  • _currentState:当前计时器状态
  • _workDuration_shortBreakDuration_longBreakDuration:各阶段的持续时间
  • _remainingTime:剩余时间(秒)
  • _completedPomodoros:完成的番茄数量
  • _currentCycle:当前循环次数
  • _timer:计时器实例
  • _tasks:任务列表
  • _newTask:新任务输入

4.2 计时器功能

dart 复制代码
void _startTimer() {
  if (_timer != null) {
    _timer!.cancel();
  }

  _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
    setState(() {
      if (_remainingTime > 0) {
        _remainingTime--;
      } else {
        _timer!.cancel();
        _completeTimer();
      }
    });
  });

  setState(() {
    if (_currentState == TimerState.stopped) {
      _currentState = TimerState.work;
      _remainingTime = _workDuration;
    } else if (_currentState == TimerState.paused) {
      _currentState = _currentState;
    }
  });
}

void _completeTimer() {
  setState(() {
    if (_currentState == TimerState.work) {
      _completedPomodoros++;
      _currentCycle++;

      if (_currentCycle % 4 == 0) {
        _currentState = TimerState.longBreak;
        _remainingTime = _longBreakDuration;
      } else {
        _currentState = TimerState.shortBreak;
        _remainingTime = _shortBreakDuration;
      }
    } else {
      _currentState = TimerState.work;
      _remainingTime = _workDuration;
    }

    _startTimer();
  });
}

代码解析

  • _startTimer 方法:启动计时器,设置定时器每秒减少剩余时间
  • _completeTimer 方法:处理计时器完成后的逻辑,包括状态切换和循环计数
  • 自动循环逻辑:每4个番茄后自动进入长休息

4.3 任务管理

dart 复制代码
void _addTask() {
  if (_newTask.isNotEmpty) {
    setState(() {
      _tasks.add(_newTask);
      _newTask = '';
    });
  }
}

void _removeTask(int index) {
  setState(() {
    _tasks.removeAt(index);
  });
}

代码解析

  • _addTask 方法:添加新任务到任务列表
  • _removeTask 方法:从任务列表中删除指定任务

4.4 时间格式化

dart 复制代码
String _formatTime(int seconds) {
  int minutes = seconds ~/ 60;
  int remainingSeconds = seconds % 60;
  return '${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}';
}

代码解析

  • _formatTime 方法:将秒数格式化为 MM:SS 格式的字符串

5. 技术亮点与创新

5.1 状态管理

  • 清晰的状态定义:使用枚举定义了计时器的不同状态,使代码结构更加清晰
  • 状态切换逻辑:实现了完整的状态切换逻辑,包括工作、休息、暂停和停止
  • 自动循环:实现了番茄工作法的自动循环功能,每4个番茄后自动进入长休息

5.2 用户界面

  • 视觉反馈:通过颜色变化提供清晰的视觉反馈,工作状态为红色,休息状态为绿色
  • 响应式布局 :使用 SingleChildScrollView 确保在不同屏幕尺寸上的良好表现
  • 卡片式设计:使用卡片式布局,使界面层次分明,易于理解

5.3 功能完整性

  • 完整的番茄工作法实现:支持标准的番茄工作法时间设置和自动循环
  • 任务管理:集成了任务管理功能,帮助用户跟踪待办事项
  • 统计功能:提供了详细的统计信息,帮助用户了解自己的工作和休息时间
  • 自定义设置:支持自定义时间设置,适应不同用户的需求

5.4 跨平台兼容性

  • Flutter 跨平台:使用 Flutter 框架,确保在 Android、iOS、Web 等平台上的一致性表现
  • 自适应设计:界面布局采用相对单位,适应不同屏幕尺寸

6. 应用场景与扩展

6.1 应用场景

  • 工作学习:帮助用户在工作和学习中保持专注,提高效率
  • 时间管理:帮助用户养成良好的时间管理习惯
  • 任务跟踪:结合任务管理功能,帮助用户跟踪和完成待办事项
  • 团队协作:在团队环境中,帮助团队成员保持专注和高效

6.2 扩展方向

  • 数据持久化:添加本地存储功能,保存用户的任务和设置
  • 云端同步:支持将数据同步到云端,实现跨设备同步
  • 通知提醒:添加系统通知,在计时器完成时提醒用户
  • 数据分析:提供更详细的数据分析,帮助用户了解自己的时间使用情况
  • 主题切换:支持不同主题风格,满足用户的个性化需求
  • 多语言支持:添加多语言支持,扩大应用的适用范围

7. 代码优化建议

7.1 性能优化

  • 计时器优化 :使用 Timer.periodic 时,确保在不需要时及时取消,避免内存泄漏
  • 状态管理优化 :对于更复杂的应用,可以使用 ProviderRiverpod 等状态管理库
  • UI 优化 :使用 RepaintBoundary 包裹复杂的 UI 组件,减少不必要的重绘

7.2 代码结构优化

  • 组件化:将 UI 组件拆分为更小的、可复用的组件
  • 逻辑分离:将业务逻辑与 UI 逻辑分离,提高代码的可维护性
  • 参数化:将时间设置、颜色等参数提取为可配置的常量

7.3 用户体验优化

  • 触觉反馈:在支持的设备上,添加触觉反馈,增强交互体验
  • 动画效果:添加更多的动画效果,使界面更加生动
  • 错误处理:添加适当的错误处理,提高应用的稳定性
  • 用户引导:添加首次使用引导,帮助用户了解应用的使用方法

8. 测试与调试

8.1 测试策略

  • 功能测试:测试计时器、任务管理、统计等核心功能
  • 性能测试:测试应用在不同设备上的性能表现
  • 兼容性测试:测试在不同平台、不同屏幕尺寸上的表现
  • 用户体验测试:测试应用的易用性和用户体验

8.2 调试技巧

  • 使用 Flutter DevTools:利用 Flutter DevTools 分析性能瓶颈和调试问题
  • 添加日志:在关键位置添加日志,便于调试
  • 使用模拟器:在不同尺寸的模拟器上测试,确保适配性
  • 用户测试:邀请用户测试,收集反馈,不断改进

9. 总结与展望

9.1 项目总结

本项目成功实现了一个功能完整的番茄时间管理应用,主要功能包括:

  • 番茄钟计时器:支持工作时间、短休息和长休息
  • 自动循环:每4个番茄后自动进入长休息
  • 任务管理:添加、删除任务
  • 统计功能:显示完成的番茄数量、工作时间和休息时间
  • 自定义设置:可调整工作时间、短休息时间和长休息时间
  • 跨平台兼容:在 Android、iOS、Web 等平台上表现一致

9.2 技术价值

  • 学习价值:展示了如何使用 Flutter 实现一个完整的时间管理应用
  • 实用价值:提供了一个可直接使用的番茄时间管理工具
  • 参考价值:为类似功能的开发提供了参考方案

9.3 未来展望

  • 智能推荐:基于用户的使用习惯,智能推荐最佳的工作和休息时间
  • 集成日历:与日历应用集成,帮助用户规划时间
  • 团队功能:添加团队协作功能,帮助团队成员协调工作
  • 健康监测:结合健康数据,提醒用户适当休息,保护身体健康
  • AI 助手:添加 AI 助手,帮助用户更好地管理时间和任务

10. 附录

10.1 完整代码

dart 复制代码
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';

enum TimerState {
  work,
  shortBreak,
  longBreak,
  paused,
  stopped,
}

void main() {
  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    statusBarIconBrightness: Brightness.dark,
  ));
  runApp(const PomodoroApp());
}

class PomodoroApp extends StatelessWidget {
  const PomodoroApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '番茄时间管理',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.red,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const PomodoroScreen(),
    );
  }
}

class PomodoroScreen extends StatefulWidget {
  const PomodoroScreen({Key? key}) : super(key: key);

  @override
  State<PomodoroScreen> createState() => _PomodoroScreenState();
}

class _PomodoroScreenState extends State<PomodoroScreen> {
  TimerState _currentState = TimerState.stopped;
  int _workDuration = 25 * 60; // 25分钟
  int _shortBreakDuration = 5 * 60; // 5分钟
  int _longBreakDuration = 15 * 60; // 15分钟
  int _remainingTime = 25 * 60;
  int _completedPomodoros = 0;
  int _currentCycle = 0;
  Timer? _timer;
  List<String> _tasks = [];
  String _newTask = '';

  void _startTimer() {
    if (_timer != null) {
      _timer!.cancel();
    }

    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        if (_remainingTime > 0) {
          _remainingTime--;
        } else {
          _timer!.cancel();
          _completeTimer();
        }
      });
    });

    setState(() {
      if (_currentState == TimerState.stopped) {
        _currentState = TimerState.work;
        _remainingTime = _workDuration;
      } else if (_currentState == TimerState.paused) {
        _currentState = _currentState;
      }
    });
  }

  void _pauseTimer() {
    if (_timer != null) {
      _timer!.cancel();
    }

    setState(() {
      _currentState = TimerState.paused;
    });
  }

  void _stopTimer() {
    if (_timer != null) {
      _timer!.cancel();
    }

    setState(() {
      _currentState = TimerState.stopped;
      _remainingTime = _workDuration;
      _currentCycle = 0;
    });
  }

  void _completeTimer() {
    setState(() {
      if (_currentState == TimerState.work) {
        _completedPomodoros++;
        _currentCycle++;

        if (_currentCycle % 4 == 0) {
          _currentState = TimerState.longBreak;
          _remainingTime = _longBreakDuration;
        } else {
          _currentState = TimerState.shortBreak;
          _remainingTime = _shortBreakDuration;
        }
      } else {
        _currentState = TimerState.work;
        _remainingTime = _workDuration;
      }

      _startTimer();
    });
  }

  void _addTask() {
    if (_newTask.isNotEmpty) {
      setState(() {
        _tasks.add(_newTask);
        _newTask = '';
      });
    }
  }

  void _removeTask(int index) {
    setState(() {
      _tasks.removeAt(index);
    });
  }

  String _formatTime(int seconds) {
    int minutes = seconds ~/ 60;
    int remainingSeconds = seconds % 60;
    return '${minutes.toString().padLeft(2, '0')}:${remainingSeconds.toString().padLeft(2, '0')}';
  }

  @override
  void dispose() {
    _timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('番茄时间管理'),
        backgroundColor: Colors.red,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            // 计时器部分
            Container(
              margin: const EdgeInsets.symmetric(vertical: 20),
              child: Column(
                children: [
                  Text(
                    _currentState == TimerState.work ? '工作时间' :
                    _currentState == TimerState.shortBreak ? '短休息' :
                    _currentState == TimerState.longBreak ? '长休息' :
                    '准备开始',
                    style: const TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 20),
                  Container(
                    width: 250,
                    height: 250,
                    decoration: BoxDecoration(
                      shape: BoxShape.circle,
                      color: _currentState == TimerState.work ? Colors.red.shade100 :
                             _currentState == TimerState.shortBreak || _currentState == TimerState.longBreak ? Colors.green.shade100 :
                             Colors.grey.shade100,
                      border: Border.all(
                        color: _currentState == TimerState.work ? Colors.red :
                               _currentState == TimerState.shortBreak || _currentState == TimerState.longBreak ? Colors.green :
                               Colors.grey,
                        width: 4,
                      ),
                    ),
                    child: Center(
                      child: Text(
                        _formatTime(_remainingTime),
                        style: TextStyle(
                          fontSize: 48,
                          fontWeight: FontWeight.bold,
                          color: _currentState == TimerState.work ? Colors.red :
                                 _currentState == TimerState.shortBreak || _currentState == TimerState.longBreak ? Colors.green :
                                 Colors.grey,
                        ),
                      ),
                    ),
                  ),
                  const SizedBox(height: 30),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      if (_currentState == TimerState.stopped || _currentState == TimerState.paused)
                        ElevatedButton(
                          onPressed: _startTimer,
                          style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.green,
                            foregroundColor: Colors.white,
                            padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
                          ),
                          child: const Text('开始'),
                        ),
                      if (_currentState != TimerState.stopped && _currentState != TimerState.paused)
                        ElevatedButton(
                          onPressed: _pauseTimer,
                          style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.orange,
                            foregroundColor: Colors.white,
                            padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
                          ),
                          child: const Text('暂停'),
                        ),
                      const SizedBox(width: 16),
                      ElevatedButton(
                        onPressed: _stopTimer,
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.red,
                          foregroundColor: Colors.white,
                          padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
                        ),
                        child: const Text('停止'),
                      ),
                    ],
                  ),
                ],
              ),
            ),

            // 统计部分
            Container(
              margin: const EdgeInsets.symmetric(vertical: 20),
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.grey.withOpacity(0.2),
                    spreadRadius: 2,
                    blurRadius: 4,
                    offset: const Offset(0, 2),
                  ),
                ],
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    '统计',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 12),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: [
                      Column(
                        children: [
                          Text(
                            '$_completedPomodoros',
                            style: const TextStyle(
                              fontSize: 24,
                              fontWeight: FontWeight.bold,
                              color: Colors.red,
                            ),
                          ),
                          const Text('完成的番茄'),
                        ],
                      ),
                      Column(
                        children: [
                          Text(
                            '${(_completedPomodoros * 25).toString()}',
                            style: const TextStyle(
                              fontSize: 24,
                              fontWeight: FontWeight.bold,
                              color: Colors.green,
                            ),
                          ),
                          const Text('工作分钟'),
                        ],
                      ),
                      Column(
                        children: [
                          Text(
                            '${((_completedPomodoros ~/ 4) * 15 + ((_completedPomodoros % 4) * 5)).toString()}',
                            style: const TextStyle(
                              fontSize: 24,
                              fontWeight: FontWeight.bold,
                              color: Colors.blue,
                            ),
                          ),
                          const Text('休息分钟'),
                        ],
                      ),
                    ],
                  ),
                ],
              ),
            ),

            // 任务管理部分
            Container(
              margin: const EdgeInsets.symmetric(vertical: 20),
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.grey.withOpacity(0.2),
                    spreadRadius: 2,
                    blurRadius: 4,
                    offset: const Offset(0, 2),
                  ),
                ],
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    '任务管理',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 12),
                  Row(
                    children: [
                      Expanded(
                        child: TextField(
                          decoration: const InputDecoration(
                            hintText: '添加任务',
                            border: OutlineInputBorder(),
                          ),
                          onChanged: (value) {
                            setState(() {
                              _newTask = value;
                            });
                          },
                          onSubmitted: (value) {
                            _addTask();
                          },
                        ),
                      ),
                      const SizedBox(width: 12),
                      ElevatedButton(
                        onPressed: _addTask,
                        style: ElevatedButton.styleFrom(
                          backgroundColor: Colors.red,
                          foregroundColor: Colors.white,
                        ),
                        child: const Text('添加'),
                      ),
                    ],
                  ),
                  const SizedBox(height: 12),
                  if (_tasks.isEmpty)
                    const Text('暂无任务'),
                  if (_tasks.isNotEmpty)
                    ListView.builder(
                      shrinkWrap: true,
                      itemCount: _tasks.length,
                      itemBuilder: (context, index) {
                        return ListTile(
                          title: Text(_tasks[index]),
                          trailing: IconButton(
                            icon: const Icon(Icons.delete),
                            onPressed: () {
                              _removeTask(index);
                            },
                          ),
                        );
                      },
                    ),
                ],
              ),
            ),

            // 设置部分
            Container(
              margin: const EdgeInsets.symmetric(vertical: 20),
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.grey.withOpacity(0.2),
                    spreadRadius: 2,
                    blurRadius: 4,
                    offset: const Offset(0, 2),
                  ),
                ],
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    '设置',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 12),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const Text('工作时间 (分钟)'),
                      Row(
                        children: [
                          IconButton(
                            icon: const Icon(Icons.remove),
                            onPressed: () {
                              setState(() {
                                if (_workDuration > 5 * 60) {
                                  _workDuration -= 5 * 60;
                                  if (_currentState == TimerState.stopped) {
                                    _remainingTime = _workDuration;
                                  }
                                }
                              });
                            },
                          ),
                          Text('${_workDuration ~/ 60}'),
                          IconButton(
                            icon: const Icon(Icons.add),
                            onPressed: () {
                              setState(() {
                                if (_workDuration < 60 * 60) {
                                  _workDuration += 5 * 60;
                                  if (_currentState == TimerState.stopped) {
                                    _remainingTime = _workDuration;
                                  }
                                }
                              });
                            },
                          ),
                        ],
                      ),
                    ],
                  ),
                  const SizedBox(height: 12),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const Text('短休息时间 (分钟)'),
                      Row(
                        children: [
                          IconButton(
                            icon: const Icon(Icons.remove),
                            onPressed: () {
                              setState(() {
                                if (_shortBreakDuration > 1 * 60) {
                                  _shortBreakDuration -= 1 * 60;
                                }
                              });
                            },
                          ),
                          Text('${_shortBreakDuration ~/ 60}'),
                          IconButton(
                            icon: const Icon(Icons.add),
                            onPressed: () {
                              setState(() {
                                if (_shortBreakDuration < 10 * 60) {
                                  _shortBreakDuration += 1 * 60;
                                }
                              });
                            },
                          ),
                        ],
                      ),
                    ],
                  ),
                  const SizedBox(height: 12),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const Text('长休息时间 (分钟)'),
                      Row(
                        children: [
                          IconButton(
                            icon: const Icon(Icons.remove),
                            onPressed: () {
                              setState(() {
                                if (_longBreakDuration > 5 * 60) {
                                  _longBreakDuration -= 5 * 60;
                                }
                              });
                            },
                          ),
                          Text('${_longBreakDuration ~/ 60}'),
                          IconButton(
                            icon: const Icon(Icons.add),
                            onPressed: () {
                              setState(() {
                                if (_longBreakDuration < 30 * 60) {
                                  _longBreakDuration += 5 * 60;
                                }
                              });
                            },
                          ),
                        ],
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

10.2 依赖项

  • flutter:Flutter 框架
  • dart:async:提供 Timer 类,用于实现倒计时功能
  • flutter/services.dart:提供 SystemChrome 类,用于设置系统 UI 样式

10.3 运行环境

  • Flutter SDK:3.0.0 或更高版本
  • Dart SDK:2.17.0 或更高版本
  • 支持的平台:Android、iOS、Web、Windows、macOS、Linux

10.4 参考资源

相关推荐
4311媒体网2 小时前
帝国CMS二次开发实战:精准实现“最新资讯”标识与高亮判断
android
浮芷.2 小时前
Flutter 框架跨平台鸿蒙开发 - 科技预言应用
科技·flutter·华为·harmonyos
李李李勃谦2 小时前
Flutter 框架跨平台鸿蒙开发 - 小众景点发现
flutter·华为·harmonyos
见山是山-见水是水2 小时前
Flutter 框架跨平台鸿蒙开发 - 邻里互助服务平台
flutter·华为·harmonyos
heimeiyingwang2 小时前
【架构实战】NewSQL数据库对比(TiDB/CockroachDB)
数据库·架构·tidb
BLUcoding2 小时前
Android 轻量级本地存储 SharedPreferences
android
提子拌饭1332 小时前
3D 旋转卡片:鸿蒙Flutter 实现的交互式 3D 卡片效果
flutter·华为·harmonyos·鸿蒙
提子拌饭1332 小时前
星芒便签:鸿蒙Flutter框架 实现的美观便签应用
flutter·华为·架构·开源·harmonyos·鸿蒙
一直在想名2 小时前
Flutter 框架跨平台鸿蒙开发 - 亲子故事共创
flutter·华为·harmonyos