生命进度条应用


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

一、项目概述

运行效果图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1 应用简介

生命进度条是一款人生可视化工具,旨在帮助用户直观地感受时间的流逝,珍惜每一天。灵感来源于经典的"生命日历"概念,将人生以周为单位可视化展示,每个小格子代表一周,让用户清晰地看到自己已经走过的人生旅程,以及还有多少时间可以珍惜。

应用以粉紫色为主色调,界面优雅温馨。用户只需输入出生日期和预期寿命,即可看到自己的人生进度条、生命周历网格、详细的时间统计数据,以及人生里程碑等丰富内容。

1.2 核心功能

功能模块 功能描述 实现方式
人生进度 显示人生完成百分比 进度条+百分比
生命周历 以周为单位的网格视图 CustomPainter绘制
时间统计 已活/剩余时间多维度统计 数据计算展示
人生里程碑 重要年龄节点标记 标签式展示
个人信息 星座、生肖、人生阶段 日期计算

1.3 人生阶段划分

年龄范围 阶段名称 特点描述
0-17岁 少年时期 成长学习阶段
18-29岁 青年时期 探索奋斗阶段
30-49岁 中年时期 事业家庭阶段
50-64岁 壮年时期 成熟稳定阶段
65岁+ 晚年时期 智慧传承阶段

1.4 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
状态管理 setState -
自定义绘制 CustomPainter -
目标平台 鸿蒙OS / Web API 21+

1.5 项目结构

lib/
└── main_life_progress.dart
    ├── LifeProgressApp           # 应用入口
    ├── LifeStats                 # 生命统计数据模型
    ├── LifeProgressHomePage      # 主页面(底部导航)
    ├── LifeGridViewport          # 生命网格视图组件
    └── LifeGridPainter           # 生命网格绘制器

二、系统架构

2.1 整体架构图

Data Layer

Presentation Layer

主页面
LifeProgressHomePage

进度页

统计页

设置页

主进度卡片

格言卡片

生命周历

快速统计

个人信息

时间分解

人生里程碑

日期设置

寿命设置

LifeStats
统计数据模型

2.2 类图设计

creates

uses

creates

uses

LifeProgressApp

+Widget build()

LifeStats

+DateTime birthDate

+int expectedAge

+DateTime now

+int totalWeeks

+int livedWeeks

+int remainingWeeks

+double progressPercent

+int totalDays

+int livedDays

+int remainingDays

+int totalMonths

+int livedMonths

+int remainingMonths

+int livedYears

+int nextBirthday

+String lifeStage

+String zodiacSign

+String chineseZodiac

LifeProgressHomePage

-DateTime _birthDate

-int _expectedAge

-int _currentIndex

-List<String> _wisdomQuotes

+void _showDatePicker()

+void _showExpectedAgeDialog()

LifeGridViewport

+LifeStats stats

+Widget build()

LifeGridPainter

+LifeStats stats

+double cellWidth

+double cellHeight

+void paint()

+bool shouldRepaint()

2.3 页面导航流程

进度

统计

设置

应用启动

是否设置生日

欢迎页面

选择出生日期

主页面

底部导航

进度页面

统计页面

设置页面

查看生命周历

查看进度百分比

查看个人信息

查看时间分解

查看人生里程碑

修改出生日期

修改预期寿命

2.4 数据计算流程

绘制器 LifeStats 页面 用户 绘制器 LifeStats 页面 用户 输入出生日期 创建统计数据 计算已活周数 计算进度百分比 计算各项统计 返回统计数据 传递统计数据 绘制网格格子 显示生命周历

三、核心模块设计

3.1 数据模型设计

3.1.1 生命统计模型 (LifeStats)
class LifeStats {
  final DateTime birthDate;    // 出生日期
  final int expectedAge;       // 预期寿命
  final DateTime now;          // 当前时间

  // 周数计算
  int get totalWeeks => expectedAge * 52;
  int get livedWeeks => now.difference(birthDate).inDays ~/ 7;
  int get remainingWeeks => totalWeeks - livedWeeks;
  
  // 进度百分比
  double get progressPercent => (livedWeeks / totalWeeks * 100).clamp(0, 100);

  // 天数计算
  int get totalDays => expectedAge * 365;
  int get livedDays => now.difference(birthDate).inDays;
  int get remainingDays => totalDays - livedDays;

  // 月数计算
  int get totalMonths => expectedAge * 12;
  int get livedMonths {
    int months = (now.year - birthDate.year) * 12 + (now.month - birthDate.month);
    if (now.day < birthDate.day) months--;
    return months.clamp(0, totalMonths);
  }
  
  // 距下次生日天数
  int get nextBirthday {
    var next = DateTime(now.year, birthDate.month, birthDate.day);
    if (next.isBefore(now) || next.isAtSameMomentAs(now)) {
      next = DateTime(now.year + 1, birthDate.month, birthDate.day);
    }
    return next.difference(now).inDays;
  }
}
3.1.2 人生阶段划分
String get lifeStage {
  if (livedYears < 18) return '少年时期';
  if (livedYears < 30) return '青年时期';
  if (livedYears < 50) return '中年时期';
  if (livedYears < 65) return '壮年时期';
  return '晚年时期';
}
3.1.3 星座计算
String get zodiacSign {
  final month = birthDate.month;
  final day = birthDate.day;
  if ((month == 1 && day >= 20) || (month == 2 && day <= 18)) return '水瓶座';
  if ((month == 2 && day >= 19) || (month == 3 && day <= 20)) return '双鱼座';
  // ... 其他星座判断
  return '摩羯座';
}
3.1.4 生肖计算
String get chineseZodiac {
  const animals = ['猴', '鸡', '狗', '猪', '鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊'];
  return animals[birthDate.year % 12];
}

3.2 页面结构设计

3.2.1 主页面布局

LifeProgressHomePage

IndexedStack

进度页

统计页

设置页

NavigationBar

进度 Tab

统计 Tab

设置 Tab

3.2.2 进度页面结构

进度页面

SliverAppBar

主进度卡片

格言卡片

生命周历卡片

快速统计卡片

渐变背景

应用图标

年龄信息

进度百分比

进度条

已过/剩余/预期

图例说明

网格视图

周数统计

3.2.3 统计页面结构

统计页面

SliverAppBar

个人信息卡片

时间分解卡片

人生里程碑卡片

预期寿命说明卡片

出生日期

当前年龄

人生阶段

星座

生肖

年进度

月进度

周进度

天进度

小时进度

分钟进度

3.3 生命网格绘制

开始绘制

计算格子尺寸

计算总行数

遍历每个格子

是否已度过

填充粉红色

填充灰色

绘制圆角矩形

是否还有格子

绘制完成


四、UI设计规范

4.1 配色方案

应用采用粉紫色为主色调,传达温馨、珍视生命的情感:

颜色类型 色值 用途
主色 #E91E63 (Pink) 导航、强调元素
辅助色 #9C27B0 (Purple) 渐变、辅助强调
深紫 #673AB7 统计页头部
深紫2 #512DA8 设置页头部
已度过 #E91E63 网格填充色
未度过 #E0E0E0 网格填充色
背景渐变 Pink → Purple 头部背景

4.2 字体规范

元素 字号 字重 颜色
应用标题 24-36px Bold #FFFFFF
页面标题 24px Bold #FFFFFF
进度百分比 24px Bold #FFFFFF
统计数值 24-28px Bold 主题色
卡片标题 18px Bold #000000
辅助文字 12-14px Regular #757575

4.3 组件规范

4.3.1 主进度卡片
┌─────────────────────────────────────────────────┐
│  人生进度                              36.25%   │
│                                                 │
│  ████████████████████░░░░░░░░░░░░░░░░░░░░░░░   │
│                                                 │
│     已过           剩余           预期          │
│     29岁           51岁           80岁          │
└─────────────────────────────────────────────────┘
4.3.2 生命网格
┌─────────────────────────────────────────────────┐
│  生命周历                     每格代表一周      │
│  █ 已度过  □ 未度过                            │
│                                                 │
│  ███████████████████████████████████████████████│
│  ███████████████████████████████████████████████│
│  ███████████████████████████████████████████████│
│  ████████████████████████████░░░░░░░░░░░░░░░░░░│
│  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│  ...                                            │
│                                                 │
│  共 4160 周 | 已过 1516 周 | 剩余 2644 周      │
└─────────────────────────────────────────────────┘
4.3.3 人生里程碑
┌─────────────────────────────────────────────────┐
│  人生里程碑                                     │
│                                                 │
│  [🎓 18岁 成年] [🎓 22岁 大学毕业]             │
│  [⭐ 30岁 而立之年] [🧠 40岁 不惑之年]         │
│  [✨ 50岁 知天命] [🎉 60岁 耳顺之年]           │
│  [❤️ 70岁 古稀之年] [🏆 80岁 耄耋之年]         │
└─────────────────────────────────────────────────┘

五、核心功能实现

5.1 生命统计计算

class LifeStats {
  final DateTime birthDate;
  final int expectedAge;
  final DateTime now;

  const LifeStats({
    required this.birthDate,
    required this.expectedAge,
    required this.now,
  });

  int get totalWeeks => expectedAge * 52;
  int get livedWeeks => now.difference(birthDate).inDays ~/ 7;
  int get remainingWeeks => totalWeeks - livedWeeks;
  double get progressPercent => (livedWeeks / totalWeeks * 100).clamp(0, 100);

  int get totalDays => expectedAge * 365;
  int get livedDays => now.difference(birthDate).inDays;
  int get remainingDays => totalDays - livedDays;

  int get livedYears => now.year - birthDate.year;
}

5.2 生命网格绘制

class LifeGridPainter extends CustomPainter {
  final LifeStats stats;
  final double cellWidth;
  final double cellHeight;

  LifeGridPainter({
    required this.stats,
    required this.cellWidth,
    required this.cellHeight,
  });

  
  void paint(Canvas canvas, Size size) {
    final livedPaint = Paint()
      ..color = const Color(0xFFE91E63)
      ..style = PaintingStyle.fill;

    final emptyPaint = Paint()
      ..color = Colors.grey.shade200
      ..style = PaintingStyle.fill;

    const columns = 52;
    var weekIndex = 0;

    for (var row = 0; weekIndex < stats.totalWeeks; row++) {
      for (var col = 0; col < columns && weekIndex < stats.totalWeeks; col++) {
        final rect = Rect.fromLTWH(
          col * cellWidth,
          row * cellHeight,
          cellWidth - 1,
          cellHeight - 1,
        );

        final isLived = weekIndex < stats.livedWeeks;
        final paint = isLived ? livedPaint : emptyPaint;

        final rrect = RRect.fromRectAndRadius(rect, const Radius.circular(2));
        canvas.drawRRect(rrect, paint);

        weekIndex++;
      }
    }
  }
}

5.3 日期选择器

void _showDatePicker() async {
  final picked = await showDatePicker(
    context: context,
    initialDate: _birthDate ?? DateTime(2000, 1, 1),
    firstDate: DateTime(1900, 1, 1),
    lastDate: DateTime.now(),
    locale: const Locale('zh', 'CN'),
    builder: (context, child) {
      return Theme(
        data: Theme.of(context).copyWith(
          colorScheme: const ColorScheme.light(
            primary: Color(0xFFE91E63),
            onPrimary: Colors.white,
          ),
        ),
        child: child!,
      );
    },
  );

  if (picked != null) {
    setState(() {
      _birthDate = picked;
    });
  }
}

5.4 预期寿命设置

void _showExpectedAgeDialog() {
  final controller = TextEditingController(text: _expectedAge.toString());
  showDialog(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text('设置预期寿命'),
      content: TextField(
        controller: controller,
        keyboardType: TextInputType.number,
        decoration: const InputDecoration(
          labelText: '预期寿命(岁)',
          suffix: Text('岁'),
        ),
      ),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('取消'),
        ),
        ElevatedButton(
          onPressed: () {
            final age = int.tryParse(controller.text);
            if (age != null && age > 0 && age <= 150) {
              setState(() {
                _expectedAge = age;
              });
              Navigator.pop(context);
            }
          },
          child: const Text('确定'),
        ),
      ],
    ),
  );
}

5.5 时间分解进度条

Widget _buildTimeRow(String unit, int lived, int total) {
  final percent = (lived / total * 100).clamp(0, 100);
  
  return Padding(
    padding: const EdgeInsets.symmetric(vertical: 8),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(unit, style: const TextStyle(fontWeight: FontWeight.w500)),
            Text('$lived / $total', style: TextStyle(color: Colors.grey.shade600)),
          ],
        ),
        const SizedBox(height: 6),
        ClipRRect(
          borderRadius: BorderRadius.circular(4),
          child: LinearProgressIndicator(
            value: percent / 100,
            backgroundColor: Colors.grey.shade200,
            valueColor: const AlwaysStoppedAnimation<Color>(Color(0xFFE91E63)),
            minHeight: 8,
          ),
        ),
      ],
    ),
  );
}

六、交互设计

6.1 首次使用流程

主页面 日期选择器 欢迎页 用户 主页面 日期选择器 欢迎页 用户 打开应用 显示欢迎界面 点击选择出生日期 展示日期选择器 选择日期 确认选择 显示生命进度

6.2 设置修改流程

出生日期

预期寿命

有效

无效

进入设置页

选择设置项

打开日期选择器

选择新日期

更新统计数据

打开输入对话框

输入新数值

验证数值

更新预期寿命

提示错误

刷新所有页面

6.3 页面切换状态

点击统计Tab

点击设置Tab

点击进度Tab

点击设置Tab

点击进度Tab

点击统计Tab

进度页

统计页

设置页

显示生命周历网格
显示进度百分比

显示个人信息
显示时间分解


七、扩展功能规划

7.1 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 生命周历 进度统计 个人信息 数据持久化 主题切换 分享功能 人生目标 时间胶囊 云端同步 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 生命进度条开发计划

7.2 功能扩展建议

7.2.1 数据持久化

保存用户设置:

  • 本地存储出生日期
  • 保存预期寿命设置
  • 记录查看历史
7.2.2 人生目标

目标追踪功能:

  • 设置人生目标
  • 标记重要事件
  • 时间线展示
7.2.3 分享功能

社交分享能力:

  • 生成精美图片
  • 分享到社交平台
  • 邀请好友一起使用

八、注意事项

8.1 开发注意事项

  1. 日期计算:使用DateTime的difference方法计算时间差

  2. 网格绘制:CustomPainter需要实现shouldRepaint方法

  3. 进度条显示:使用clamp确保百分比在0-100范围内

  4. 本地化:日期选择器需要设置中文locale

8.2 常见问题

问题 原因 解决方案
进度超过100% 预期寿命设置过低 使用clamp限制
网格显示不全 高度计算错误 使用SingleChildScrollView
日期选择器英文 未设置locale 添加Locale(‘zh’, ‘CN’)
生肖计算错误 年份取模错误 检查取模运算

8.3 使用提示

⏳ 生命进度条使用小贴士 ⏳

每一个小格子代表你生命中的一周。
看着已经填满的格子,珍惜剩余的空白。
时间是最公平的资源,每个人每天都只有24小时。
不要让昨天占据今天太多的时间。


九、运行说明

9.1 环境要求

环境 版本要求
Flutter SDK >= 3.0.0
Dart SDK >= 2.17.0
鸿蒙OS API 21+

9.2 运行命令

# 查看可用设备
flutter devices

# 运行到Web服务器
flutter run -d web-server -t lib/main_life_progress.dart --web-port 8121

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_life_progress.dart

# 运行到Windows
flutter run -d windows -t lib/main_life_progress.dart

# 代码分析
flutter analyze lib/main_life_progress.dart

十、总结

生命进度条通过直观的可视化方式,帮助用户感受时间的流逝,珍惜每一天。应用以周为单位展示人生旅程,每个小格子代表一周,让用户清晰地看到自己已经走过的人生,以及还有多少时间可以珍惜。

核心功能涵盖生命周历、进度统计、个人信息、人生里程碑四大模块。生命周历以网格形式展示,已度过的周用粉红色填充,未度过的用灰色表示;进度统计显示精确的百分比和各项时间数据;个人信息包含星座、生肖、人生阶段等趣味信息;人生里程碑标记了18岁成年、30而立等重要节点。

应用采用Material Design 3设计规范,以粉紫色为主色调,界面温馨优雅。通过本应用,希望能够帮助用户更加珍惜时间,活在当下,让每一天都过得有意义。

珍惜每一天,活在当下

Logo

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

更多推荐