#请添加图片描述

前言

睡眠分析页面帮助用户了解自己的睡眠规律和质量。通过统计本周的睡眠数据,用户可以发现自己的睡眠问题,调整作息习惯。

这篇文章会讲解睡眠分析页面的实现,包括平均睡眠时长展示、入睡起床时间统计、本周睡眠柱状图等功能。


页面整体结构

睡眠分析页面包含汇总数据卡片和本周睡眠统计两个主要部分。

class SleepAnalysisPage extends StatelessWidget {
  const SleepAnalysisPage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFFAFAFC),
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        leading: IconButton(
          icon: Icon(Icons.arrow_back_ios_rounded, size: 20.w), 
          onPressed: () => Get.back()
        ),
        title: Text('睡眠分析', style: TextStyle(fontSize: 17.sp, fontWeight: FontWeight.w600)),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(20.w),
        child: Column(
          children: [
            _buildSummaryCard(),
            SizedBox(height: 20.h),
            _buildWeekStats(),
          ],
        ),
      ),
    );
  }
}

页面使用统一的浅灰色背景和透明 AppBar,和其他统计页面保持一致的视觉风格。


睡眠汇总卡片

汇总卡片使用紫色渐变背景,展示本周平均睡眠时长和相关统计数据。

Widget _buildSummaryCard() {
  return Container(
    padding: EdgeInsets.all(24.w),
    decoration: BoxDecoration(
      gradient: const LinearGradient(
        colors: [Color(0xFF845EC2), Color(0xFFA178DF)]
      ),
      borderRadius: BorderRadius.circular(24.r),
    ),
    child: Column(
      children: [
        Text('本周平均睡眠', style: TextStyle(fontSize: 13.sp, color: Colors.white70)),
        SizedBox(height: 8.h),
        Text('7小时15分', style: TextStyle(
          fontSize: 32.sp, 
          fontWeight: FontWeight.w700, 
          color: Colors.white
        )),
        SizedBox(height: 16.h),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            _buildMiniStat('入睡', '23:12'),
            _buildMiniStat('起床', '06:27'),
            _buildMiniStat('质量', '良好'),
          ],
        ),
      ],
    ),
  );
}

Widget _buildMiniStat(String label, String value) {
  return Column(
    children: [
      Text(value, style: TextStyle(
        fontSize: 16.sp, 
        fontWeight: FontWeight.w600, 
        color: Colors.white
      )),
      SizedBox(height: 2.h),
      Text(label, style: TextStyle(fontSize: 11.sp, color: Colors.white60)),
    ],
  );
}

渐变色从 #845EC2#A178DF,是一个优雅的紫色系,和睡眠主题非常契合。平均睡眠时长使用 32sp 的大字号居中显示。

底部三个迷你统计项展示平均入睡时间、平均起床时间和睡眠质量评估。用 spaceAround 让三个项目均匀分布。


睡眠质量评估

根据平均睡眠时长评估睡眠质量:

String _getSleepQuality(double avgHours) {
  if (avgHours < 6) {
    return '不足';
  } else if (avgHours < 7) {
    return '一般';
  } else if (avgHours <= 8) {
    return '良好';
  } else if (avgHours <= 9) {
    return '很好';
  } else {
    return '过多';
  }
}

成年人建议每天睡 7-9 小时,低于 6 小时为睡眠不足,超过 9 小时可能也不太健康。这个方法根据平均时长返回对应的质量评价。


本周睡眠柱状图

柱状图直观地展示本周每天的睡眠时长,让用户一眼看出哪天睡得好、哪天睡得少。

Widget _buildWeekStats() {
  final days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
  final hours = [7.5, 6.8, 8.0, 7.2, 6.5, 8.5, 7.3];

  return Container(
    padding: EdgeInsets.all(20.w),
    decoration: BoxDecoration(
      color: Colors.white, 
      borderRadius: BorderRadius.circular(20.r)
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('本周睡眠', style: TextStyle(
          fontSize: 16.sp, 
          fontWeight: FontWeight.w600, 
          color: const Color(0xFF1A1A2E)
        )),
        SizedBox(height: 20.h),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: List.generate(7, (i) => Column(
            children: [
              Container(
                width: 32.w,
                height: (hours[i] * 16).h,
                decoration: BoxDecoration(
                  color: hours[i] >= 7 
                    ? const Color(0xFF845EC2) 
                    : const Color(0xFF845EC2).withOpacity(0.3),
                  borderRadius: BorderRadius.circular(6.r),
                ),
              ),
              SizedBox(height: 8.h),
              Text(days[i], style: TextStyle(fontSize: 10.sp, color: Colors.grey[500])),
            ],
          )),
        ),
      ],
    ),
  );
}

柱状图的高度根据睡眠时长动态计算,hours[i] * 16 把小时数转换成像素高度。睡眠达到 7 小时以上的用实心紫色,不足 7 小时的用淡紫色,让用户能快速识别睡眠不足的日子。

每个柱子下方显示星期几的标签,用灰色小字不会太抢眼。


柱状图高度计算

为了让柱状图显示效果更好,可以动态计算高度比例:

double _calculateBarHeight(double hours, double maxHours) {
  final maxHeight = 120.h; // 最大高度
  final minHeight = 20.h;  // 最小高度
  
  if (maxHours == 0) return minHeight;
  
  final ratio = hours / maxHours;
  return minHeight + (maxHeight - minHeight) * ratio;
}

这个方法根据当前值和最大值计算柱子高度,确保最高的柱子不会太高,最矮的柱子也不会太矮。


睡眠规律分析

除了时长,睡眠规律也很重要。可以分析用户的入睡和起床时间是否规律:

Widget _buildRegularityAnalysis() {
  return Container(
    padding: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(16.r),
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('作息规律', style: TextStyle(
          fontSize: 14.sp,
          fontWeight: FontWeight.w500,
          color: const Color(0xFF1A1A2E),
        )),
        SizedBox(height: 12.h),
        _buildRegularityItem('入睡时间', '22:45 - 23:30', '波动45分钟'),
        SizedBox(height: 10.h),
        _buildRegularityItem('起床时间', '06:15 - 07:00', '波动45分钟'),
        SizedBox(height: 12.h),
        Container(
          padding: EdgeInsets.all(10.w),
          decoration: BoxDecoration(
            color: const Color(0xFF845EC2).withOpacity(0.08),
            borderRadius: BorderRadius.circular(8.r),
          ),
          child: Row(
            children: [
              Icon(Icons.check_circle_outline_rounded, size: 16.w, color: const Color(0xFF845EC2)),
              SizedBox(width: 8.w),
              Expanded(
                child: Text(
                  '您的作息比较规律,继续保持',
                  style: TextStyle(fontSize: 12.sp, color: const Color(0xFF845EC2)),
                ),
              ),
            ],
          ),
        ),
      ],
    ),
  );
}

Widget _buildRegularityItem(String label, String range, String variance) {
  return Row(
    children: [
      SizedBox(
        width: 70.w,
        child: Text(label, style: TextStyle(fontSize: 13.sp, color: Colors.grey[600])),
      ),
      Expanded(
        child: Text(range, style: TextStyle(
          fontSize: 14.sp,
          fontWeight: FontWeight.w500,
          color: const Color(0xFF1A1A2E),
        )),
      ),
      Text(variance, style: TextStyle(fontSize: 11.sp, color: Colors.grey[400])),
    ],
  );
}

规律分析展示入睡和起床时间的范围以及波动幅度。波动越小说明作息越规律,对健康越有益。


睡眠建议

根据睡眠数据生成个性化的建议:

List<String> _generateSleepTips(double avgHours, double variance) {
  List<String> tips = [];
  
  if (avgHours < 7) {
    tips.add('您的平均睡眠时间不足7小时,建议早点入睡');
  } else if (avgHours > 9) {
    tips.add('睡眠时间过长可能影响精力,建议控制在7-9小时');
  } else {
    tips.add('您的睡眠时长在健康范围内,继续保持');
  }
  
  if (variance > 60) {
    tips.add('作息时间波动较大,建议固定入睡和起床时间');
  } else {
    tips.add('您的作息比较规律,这对健康很有益');
  }
  
  tips.add('睡前避免使用电子设备,有助于提高睡眠质量');
  
  return tips;
}

建议内容根据平均睡眠时长和作息规律动态生成,给用户提供有针对性的指导。


睡眠趋势对比

可以添加和上周的对比,让用户了解自己的睡眠变化:

Widget _buildWeekComparison() {
  return Container(
    padding: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(16.r),
    ),
    child: Row(
      children: [
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('与上周对比', style: TextStyle(
                fontSize: 14.sp,
                fontWeight: FontWeight.w500,
                color: const Color(0xFF1A1A2E),
              )),
              SizedBox(height: 4.h),
              Text('平均睡眠时长', style: TextStyle(
                fontSize: 11.sp,
                color: Colors.grey[400],
              )),
            ],
          ),
        ),
        Row(
          children: [
            Icon(Icons.arrow_upward_rounded, size: 16.w, color: const Color(0xFF00C9A7)),
            SizedBox(width: 4.w),
            Text('+18分钟', style: TextStyle(
              fontSize: 16.sp,
              fontWeight: FontWeight.w600,
              color: const Color(0xFF00C9A7),
            )),
          ],
        ),
      ],
    ),
  );
}

对比数据用箭头和颜色表示变化方向,增加显示绿色向上箭头,减少显示红色向下箭头。


睡眠目标达成

展示本周睡眠目标的达成情况:

Widget _buildGoalAchievement() {
  final targetDays = 7;
  final achievedDays = 5; // 达到7小时以上的天数
  
  return Container(
    padding: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(16.r),
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text('睡眠目标', style: TextStyle(
              fontSize: 14.sp,
              fontWeight: FontWeight.w500,
              color: const Color(0xFF1A1A2E),
            )),
            Text('$achievedDays/$targetDays 天', style: TextStyle(
              fontSize: 14.sp,
              fontWeight: FontWeight.w600,
              color: const Color(0xFF845EC2),
            )),
          ],
        ),
        SizedBox(height: 12.h),
        Row(
          children: List.generate(7, (i) => Expanded(
            child: Container(
              margin: EdgeInsets.only(right: i < 6 ? 4.w : 0),
              height: 6.h,
              decoration: BoxDecoration(
                color: i < achievedDays 
                  ? const Color(0xFF845EC2) 
                  : Colors.grey[200],
                borderRadius: BorderRadius.circular(3.r),
              ),
            ),
          )),
        ),
        SizedBox(height: 8.h),
        Text(
          '每天睡眠7小时以上',
          style: TextStyle(fontSize: 11.sp, color: Colors.grey[400]),
        ),
      ],
    ),
  );
}

用七个小方块表示一周七天,达成目标的用紫色填充,未达成的用灰色。这种可视化方式让用户一眼就能看出自己的达成情况。


小结

睡眠分析页面通过紫色渐变卡片展示平均数据,用柱状图直观呈现每日睡眠时长,再配合规律分析和目标达成展示,帮助用户全面了解自己的睡眠状况。

核心设计要点包括:柱状图用颜色深浅区分达标与否,规律分析展示时间波动范围,目标达成用进度条可视化。这些设计让用户能发现自己的睡眠问题,有针对性地改善作息习惯。


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

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐