import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; const Duration _kHomeMineSkeletonAnimationDuration = Duration( milliseconds: 1450, ); const Color _kHomeMineSkeletonShell = Color(0xFF0F3730); const Color _kHomeMineSkeletonShellStrong = Color(0xFF1A4A41); const Color _kHomeMineSkeletonBoneBase = Color(0xFF2B5C53); const Color _kHomeMineSkeletonBoneHighlight = Color(0xFF5F8177); const Color _kHomeMineSkeletonBorder = Color(0x66D8B57B); class SCHomeSkeletonShimmer extends StatefulWidget { const SCHomeSkeletonShimmer({super.key, required this.builder}); final Widget Function(BuildContext context, double progress) builder; @override State createState() => _SCHomeSkeletonShimmerState(); } class _SCHomeSkeletonShimmerState extends State with SingleTickerProviderStateMixin { late final AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: _kHomeMineSkeletonAnimationDuration, )..repeat(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _controller, builder: (context, child) => widget.builder(context, _controller.value), ); } } BoxDecoration buildHomeSkeletonShellDecoration({ required double radius, EdgeInsetsGeometry? padding, }) { return BoxDecoration( borderRadius: BorderRadius.circular(radius), border: Border.all(color: _kHomeMineSkeletonBorder, width: 1.w), gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [_kHomeMineSkeletonShellStrong, _kHomeMineSkeletonShell], ), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.16), blurRadius: 16.w, offset: Offset(0, 8.w), ), ], ); } Widget buildHomeSkeletonBlock( double progress, { double? width, required double height, BorderRadius? borderRadius, BoxShape shape = BoxShape.rectangle, }) { final double slideOffset = (progress * 2) - 1; return Container( width: width, height: height, decoration: BoxDecoration( shape: shape, borderRadius: shape == BoxShape.circle ? null : (borderRadius ?? BorderRadius.circular(10.w)), gradient: LinearGradient( begin: Alignment(-1.4 + slideOffset, -0.2), end: Alignment(1.4 + slideOffset, 0.2), colors: const [ _kHomeMineSkeletonBoneBase, _kHomeMineSkeletonBoneBase, _kHomeMineSkeletonBoneHighlight, _kHomeMineSkeletonBoneBase, ], stops: const [0.0, 0.36, 0.54, 1.0], ), ), ); } Widget buildHomeMyRoomSkeleton(double progress) { return Container( margin: EdgeInsets.symmetric(horizontal: 12.w), width: double.infinity, height: 85.w, decoration: buildHomeSkeletonShellDecoration(radius: 16.w), child: Padding( padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 8.w), child: Row( children: [ buildHomeSkeletonBlock( progress, width: 70.w, height: 70.w, borderRadius: BorderRadius.circular(10.w), ), SizedBox(width: 10.w), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Row( children: [ buildHomeSkeletonBlock( progress, width: 18.w, height: 14.w, borderRadius: BorderRadius.circular(3.w), ), SizedBox(width: 5.w), buildHomeSkeletonBlock( progress, width: 110.w, height: 14.w, borderRadius: BorderRadius.circular(999.w), ), ], ), SizedBox(height: 9.w), buildHomeSkeletonBlock( progress, width: 170.w, height: 12.w, borderRadius: BorderRadius.circular(999.w), ), SizedBox(height: 8.w), buildHomeSkeletonBlock( progress, width: 76.w, height: 10.w, borderRadius: BorderRadius.circular(999.w), ), ], ), ), SizedBox(width: 10.w), buildHomeSkeletonBlock( progress, width: 24.w, height: 24.w, shape: BoxShape.circle, ), ], ), ), ); } Widget buildHomeRoomGridSkeleton( double progress, { int itemCount = 6, EdgeInsetsGeometry? padding, }) { return GridView.builder( shrinkWrap: true, padding: padding ?? EdgeInsets.symmetric(horizontal: 5.w), physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 1, mainAxisSpacing: 10, crossAxisSpacing: 10, ), itemCount: itemCount, itemBuilder: (context, index) => buildHomeRoomCardSkeleton(progress), ); } Widget buildHomeRoomCardSkeleton(double progress) { return Container( margin: EdgeInsets.symmetric(horizontal: 5.w, vertical: 5.w), decoration: BoxDecoration( borderRadius: BorderRadius.circular(14.w), border: Border.all(color: _kHomeMineSkeletonBorder, width: 1.w), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.16), blurRadius: 16.w, offset: Offset(0, 8.w), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(14.w), child: Stack( alignment: Alignment.bottomCenter, children: [ Positioned.fill( child: DecoratedBox( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ _kHomeMineSkeletonShellStrong, _kHomeMineSkeletonShell, ], ), ), ), ), Positioned.fill( child: Padding( padding: EdgeInsets.only(bottom: 34.w), child: buildHomeSkeletonBlock( progress, height: double.infinity, borderRadius: BorderRadius.vertical(top: Radius.circular(14.w)), ), ), ), Positioned( top: 12.w, right: 12.w, child: buildHomeSkeletonBlock( progress, width: 30.w, height: 12.w, borderRadius: BorderRadius.circular(999.w), ), ), Positioned( left: 0, right: 0, bottom: 0, child: Container( height: 34.w, padding: EdgeInsets.symmetric(horizontal: 10.w), decoration: BoxDecoration( color: Colors.black.withValues(alpha: 0.24), border: Border( top: BorderSide( color: Colors.white.withValues(alpha: 0.05), width: 1.w, ), ), ), child: Row( children: [ buildHomeSkeletonBlock( progress, width: 20.w, height: 13.w, borderRadius: BorderRadius.circular(3.w), ), SizedBox(width: 6.w), Expanded( child: buildHomeSkeletonBlock( progress, height: 10.w, borderRadius: BorderRadius.circular(999.w), ), ), SizedBox(width: 8.w), buildHomeSkeletonBlock( progress, width: 18.w, height: 10.w, borderRadius: BorderRadius.circular(999.w), ), ], ), ), ), ], ), ), ); }