Flutter---睡眠卡片

效果图

实现步骤

1.定义变量

Dart 复制代码
  late AnimationController _controller; //动画控制器
  late Animation<double> _animation; //动画值

2.初始化

Dart 复制代码
  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      duration: Duration(milliseconds: 1500), //动画时长
      vsync: this, //同步信号源
    );

    //进度条绘制比例 86/100
    _animation = Tween<double>(begin: 0, end: 0.86).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeOut),
    );
    //启动动画
    _controller.forward();

  }

3.注销

Dart 复制代码
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

4.仪表盘背景绘制器

Dart 复制代码
class GaugeBackgroundPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2); //圆心
    final radius = size.width / 2 - 5; //半径

    final backgroundPaint = Paint()
      ..color = Colors.white.withOpacity(0.3)
      ..style = PaintingStyle.stroke //描边模式
      ..strokeWidth = 5  //线宽5像素
      ..strokeCap = StrokeCap.round; //线端圆角

    // 绘制背景圆弧(240度,从-230度到280度)
    final rect = Rect.fromCircle(
        center: center, //圆心坐标
        radius: radius //圆的半径
    );
    canvas.drawArc(
        rect, //限定圆弧的矩形区域
        -230 * pi / 180, //起始角度 -230°
        280 * pi / 180, //扫过的角度 280°
        false,  //是否连接圆心
        backgroundPaint //画笔配置
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

5.仪表盘进度绘制器

Dart 复制代码
class GaugeProgressPainter extends CustomPainter {
  final double progress; //进度值

  GaugeProgressPainter({required this.progress});

  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2); //圆心
    final radius = size.width / 2 - 5; //半径

    final rect = Rect.fromCircle(center: center, radius: radius);

    final progressPaint = Paint()

      ..style = PaintingStyle.stroke
      ..strokeWidth = 5
      ..strokeCap = StrokeCap.round
      ..shader = LinearGradient(
        colors: [
          Color(0xFF0DCCFF),  // 开始颜色
          Color(0xFF4760FF),  // 结束颜色
        ],
        begin: Alignment(-1.0, 0.0),  // 左侧开始
        end: Alignment(1.0, 0.0),     // 右侧结束
        tileMode: TileMode.clamp,
      ).createShader(rect);

    // 计算进度对应的角度(从-230度开始)
    final startAngle = -230 * pi / 180;
    final sweepAngle = 280 * pi / 180 * progress;


    canvas.drawArc(rect, startAngle, sweepAngle, false, progressPaint);

  }

  @override
  bool shouldRepaint(covariant GaugeProgressPainter oldDelegate) =>
      oldDelegate.progress != progress;
}

6.睡眠详情--条形进度条的子项

Dart 复制代码
Widget _buildSleepDetailBar(String title, String value, Color color, double widthFactor) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Text(
              title,
              style: TextStyle(
                color: Colors.white,
                fontSize: 10,
              ),
            ),
            Spacer(),
            Text(
              value,
              style: TextStyle(
                color: Colors.white.withOpacity(0.8),
                fontSize: 10,
              ),
            ),
          ],
        ),
        SizedBox(height: 4),

        // 添加背景条的容器
        Container(
          width: MediaQuery.of(context).size.width * 0.4, // 背景条总宽度
          height: 4,
          decoration: BoxDecoration(
            color: Colors.white.withOpacity(0.3), //背景条颜色
            borderRadius: BorderRadius.circular(2),
          ),
          child: Align(
            alignment: Alignment.centerLeft,
            child: Container(
              height: 4,
              width: MediaQuery.of(context).size.width * 0.4 * widthFactor, // 彩色进度条宽度
              decoration: BoxDecoration(
                color: color,
                borderRadius: BorderRadius.circular(2),
              ),
            ),
          ),
        ),
      ],
    );
  }

7.定义UI架构

Dart 复制代码
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,

      //滚动视图
      body: SingleChildScrollView(
        physics: BouncingScrollPhysics(), //回弹滚动效果
        child: Column(

          children: [
            SizedBox(height: 150),

            // 睡眠得分卡片
            _buildSleepScoreCard(),
            SizedBox(height: 20),

          ],
        ),
      ),
    );
  }

8.详细的进度条布局

Dart 复制代码
Widget _buildSleepScoreCard() {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 16),
      padding: EdgeInsets.all(24),
      decoration: BoxDecoration(
        color: Color(0xFF1B1D2E),
        borderRadius: BorderRadius.circular(20),
      ),
      child: Column(
        children: [
          // 睡眠得分和仪表盘式进度条
          Row(
            children: [
              //左侧的仪表盘
              Container(
                width: 120,
                height: 120,
                child: Stack(
                  alignment: Alignment.center,
                  children: [
                    // 仪表盘背景
                    CustomPaint(
                      size: Size(120, 120),
                      painter: GaugeBackgroundPainter(),
                    ),

                    // 仪表盘动态进度条
                    AnimatedBuilder(
                      animation: _animation,
                      builder: (context, child) {
                        return CustomPaint(
                          size: Size(120, 120),
                          painter: GaugeProgressPainter(progress: _animation.value),
                        );
                      },
                    ),

                    // 中间的文本
                    Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        AnimatedBuilder(
                          animation: _animation,
                          builder: (context, child) {
                            return Text(
                              '${(_animation.value * 100).toInt()}',
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 24,
                                fontWeight: FontWeight.bold,
                              ),
                            );
                          },
                        ),
                        Text(
                          "睡眠得分",
                          style: TextStyle(
                            color: Colors.white.withOpacity(0.8),
                            fontSize: 9,
                          ),
                        ),
                        Text(
                          "23:20-06:35",
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 12,
                          ),
                        ),
                        Text(
                          "入睡时间",
                          style: TextStyle(
                            color: Colors.white.withOpacity(0.8),
                            fontSize: 9,
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),

              SizedBox(width: 20),

              // 右侧条形图区域
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [

                    // 睡眠时长详情
                    _buildSleepDetailBar("深睡", "3小时52分", Colors.blue, 0.385),
                    SizedBox(height: 8),
                    _buildSleepDetailBar("浅睡", "2小时52分", Colors.purple, 0.26),
                    SizedBox(height: 8),
                    _buildSleepDetailBar("清醒", "1次/16分", Colors.orange, 0.027),
                  ],
                ),
              ),
            ],
          ),

        ],
      ),
    );
  }
相关推荐
西西学代码12 小时前
Flutter---动画
flutter
码农汉子13 小时前
构建属于自己的Flutter混合开发框架
flutter·dart
xkxnq15 小时前
第一阶段:Vue 基础入门(第 8 天)
前端·vue.js·flutter
kirk_wang15 小时前
Flutter flutter_pdfview 在 OpenHarmony 平台的适配实战:原理与实现指南
flutter·移动开发·跨平台·arkts·鸿蒙
西西学代码1 天前
Flutter---CustomPaint
学习·flutter
火柴就是我1 天前
flutter 实现文本贴图
flutter
Swift社区1 天前
Flutter / RN / iOS 的 UI 渲染机制,本质差异在哪里?
flutter·ui·ios
小蜜蜂嗡嗡1 天前
flutter可吸边且隐藏一半的拖拽悬浮按钮
flutter
AiFlutter1 天前
三、内容展示(04):条形码
flutter·低代码平台·aiflutter·aiflutter低代码·flutter低代码开发