【flutter for open harmony】第三方库Flutter 鸿蒙版 时钟 实战指南(适配 1.0.0)✨

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

本文详细介绍如何在Flutter鸿蒙应用中实现时钟功能,包括模拟表盘、数字时间和日期显示。

一、前言

时钟是最基础也是最常用的工具之一,本文将介绍如何在Flutter鸿蒙应用中实现时钟功能,包括模拟表盘和数字时间显示。

二、效果展示

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b6627ab2ced24093b4002628aecb56e3.png

2.1 功能特性

功能 描述
模拟表盘 圆形表盘显示时针、分针、秒针
数字时间 数字格式显示当前时间
日期显示 显示当前日期和星期
实时更新 每秒更新时间显示

三、项目背景与目标

3.1 项目背景

时钟是应用中常见的组件,通过实现时钟功能可以学习Flutter的自定义绘制和定时更新。

3.2 项目目标

  • 实现模拟表盘绘制
  • 实现数字时间显示
  • 实现日期显示
  • 实现实时更新

四、技术架构设计

4.1 架构概述

时钟应用使用Flutter的CustomPaint绘制模拟表盘,通过Timer实现每秒更新。

4.2 时钟指针角度计算

  • 时针角度 = (小时 % 12) * 30 + 分钟 * 0.5
  • 分针角度 = 分钟 * 6
  • 秒针角度 = 秒 * 6

五、详细实现

5.1 Flutter端实现

import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';

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

  
  State<SimpleClockPage> createState() => _SimpleClockPageState();
}

class _SimpleClockPageState extends State<SimpleClockPage> {
  Timer? _timer;
  DateTime _now = DateTime.now();

  
  void initState() {
    super.initState();
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        _now = DateTime.now();
      });
    });
  }

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('时钟'),
        centerTitle: true,
        backgroundColor: Colors.indigo,
        foregroundColor: Colors.white,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            SizedBox(
              width: 300,
              height: 300,
              child: CustomPaint(
                painter: ClockPainter(_now),
              ),
            ),
            const SizedBox(height: 32),
            Text(
              '${_now.hour.toString().padLeft(2, '0')}:${_now.minute.toString().padLeft(2, '0')}:${_now.second.toString().padLeft(2, '0')}',
              style: const TextStyle(
                fontSize: 48,
                fontWeight: FontWeight.bold,
                color: Colors.indigo,
                letterSpacing: 4,
              ),
            ),
            const SizedBox(height: 8),
            Text(
              '${_now.year}${_now.month}${_now.day}日',
              style: TextStyle(fontSize: 20, color: Colors.grey[600]),
            ),
            const SizedBox(height: 8),
            Text(
              ['一', '二', '三', '四', '五', '六', '日'][_now.weekday - 1],
              style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.indigo),
            ),
          ],
        ),
      ),
    );
  }
}

class ClockPainter extends CustomPainter {
  final DateTime time;

  ClockPainter(this.time);

  
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = size.width / 2 - 20;

    final bgPaint = Paint()
      ..color = Colors.indigo.withOpacity(0.1)
      ..style = PaintingStyle.fill;
    canvas.drawCircle(center, radius, bgPaint);

    final borderPaint = Paint()
      ..color = Colors.indigo
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3;
    canvas.drawCircle(center, radius, borderPaint);

    final textPainter = TextPainter(textDirection: TextDirection.ltr);
    for (int i = 1; i <= 12; i++) {
      final angle = (i * 30 - 90) * 3.14159 / 180;
      final x = center.dx + (radius - 30) * cos(angle);
      final y = center.dy + (radius - 30) * sin(angle);
      
      textPainter.text = TextSpan(
        text: '$i',
        style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.indigo),
      );
      textPainter.layout();
      textPainter.paint(canvas, Offset(x - textPainter.width / 2, y - textPainter.height / 2));
    }

    final hourAngle = ((time.hour % 12) * 30 + time.minute * 0.5 - 90) * 3.14159 / 180;
    final hourPaint = Paint()
      ..color = Colors.indigo
      ..strokeWidth = 6
      ..strokeCap = StrokeCap.round;
    canvas.drawLine(center, Offset(center.dx + 60 * cos(hourAngle), center.dy + 60 * sin(hourAngle)), hourPaint);

    final minuteAngle = (time.minute * 6 - 90) * 3.14159 / 180;
    final minutePaint = Paint()
      ..color = Colors.indigo[300]!
      ..strokeWidth = 4
      ..strokeCap = StrokeCap.round;
    canvas.drawLine(center, Offset(center.dx + 80 * cos(minuteAngle), center.dy + 80 * sin(minuteAngle)), minutePaint);

    final secondAngle = (time.second * 6 - 90) * 3.14159 / 180;
    final secondPaint = Paint()
      ..color = Colors.red
      ..strokeWidth = 2
      ..strokeCap = StrokeCap.round;
    canvas.drawLine(center, Offset(center.dx + 90 * cos(secondAngle), center.dy + 90 * sin(secondAngle)), secondPaint);

    canvas.drawCircle(center, 8, Paint()..color = Colors.indigo);
  }

  
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

5.2 核心功能解析

表盘绘制

使用CustomPainter绘制圆形表盘、刻度数字和指针。

指针角度计算

根据时间计算指针角度,注意角度需要减去90度(因为0度指向右侧)。

实时更新

使用Timer.periodic每秒触发setState更新UI。

六、实际应用场景

6.1 桌面时钟

作为桌面时钟应用使用。

6.2 时间显示

在应用中显示当前时间。

6.3 学习示例

学习Flutter自定义绘制。

七、优化建议

7.1 主题切换

支持多种表盘主题。

7.2 秒针平滑

使用动画实现秒针平滑移动。

7.3 世界时钟

添加多时区显示功能。

八、常见问题与解决方案

8.1 指针角度错误

确保角度计算正确,注意三角函数参数为弧度。

8.2 更新不及时

检查Timer是否正确设置和取消。

8.3 内存泄漏

确保在dispose中取消Timer。

九、总结

本文详细介绍了Flutter鸿蒙时钟功能的实现过程,包括模拟表盘绘制、数字时间显示和实时更新。通过本实例,开发者可以掌握Flutter自定义绘制、Timer使用、数学计算等关键技术点。

十、参考资料

  • Flutter官方文档:https://flutter.dev
  • HarmonyOS开发者文档:https://developer.harmonyos.com
  • Flutter中国社区:https://flutter-io.cn
Logo

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

更多推荐