import 'package:flutter/material.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/component/home_page/SleepDataModuleWidget.dart'; import 'package:EasyDartModule/EasyDartModule.dart' as es; class BreatheCard extends StatefulWidget { var sleepReport; final int? highlightItem; BreatheCard({super.key, required this.sleepReport, this.highlightItem}); @override State createState() => _BreatheCardState(); } class _BreatheCardState extends State with TickerProviderStateMixin { final GlobalKey _highlightKey = GlobalKey(); AnimationController? _animationController; bool _shouldAnimate = false; int? _highlightedId; int _flashCount = 0; @override void initState() { super.initState(); if (widget.highlightItem != null) { _highlightedId = widget.highlightItem; _shouldAnimate = true; _initAnimation(); } WidgetsBinding.instance.addPostFrameCallback((_) { if (widget.highlightItem != null && _highlightKey.currentContext != null) { Scrollable.ensureVisible( _highlightKey.currentContext!, duration: Duration(milliseconds: 500), curve: Curves.easeInOut, alignment: 0.3, ); } }); } void _initAnimation() { _animationController = AnimationController( vsync: this, duration: Duration(milliseconds: 300), )..addStatusListener((status) { if (status == AnimationStatus.completed) { _animationController!.reverse(); } else if (status == AnimationStatus.dismissed) { _flashCount++; if (_flashCount >= 3) { _animationController!.dispose(); setState(() { _shouldAnimate = false; _highlightedId = null; }); } else { _animationController!.forward(); } } }); _animationController!.forward(); } @override void dispose() { _animationController?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { try { if (widget.sleepReport == null || widget.sleepReport is! Map || widget.sleepReport.isEmpty) { return Container(); } // List data = widget.sleepReport['brs'] ?? []; List data = widget.sleepReport['brs'] ?? []; data = data.where((item) { return item['show'] != false; // 只保留 show 不为 false 的元素 }).toList(); // 添加 .toList() return Container( width: double.infinity, decoration: BoxDecoration( color: themeController.currentColor.sc5, borderRadius: BorderRadius.circular(AppConstants().normal_container_radius), ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB(26.rpx, 29.rpx, 26.rpx, 45.rpx), child: Wrap( spacing: 23.rpx, runSpacing: 25.rpx, children: List.generate(data.length, (index) { final item = data[index]; item['showTip'] = true; final bool isHighlighted = _shouldAnimate && item['id'] == _highlightedId; return SizedBox( width: (MediaQuery.of(context).size.width - 160.rpx) / 3, child: AnimatedBuilder( animation: _animationController ?? AlwaysStoppedAnimation(0), builder: (context, child) { return Container( key: isHighlighted ? _highlightKey : null, decoration: isHighlighted ? BoxDecoration( border: Border.all( color: themeController.currentColor.sc2 .withOpacity( _animationController?.value ?? 0), width: 1.rpx, ), borderRadius: BorderRadius.circular(8), ) : null, child: SleepDataModuleWidget(data: item), ); }, ), ); }), ), ), ); } catch (e) { es.EasyDartModule.logger.error("呼吸监测绘制异常${e}"); return Container(); } } }