294 lines
8.5 KiB
Dart
294 lines
8.5 KiB
Dart
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<SCHomeSkeletonShimmer> createState() => _SCHomeSkeletonShimmerState();
|
|
}
|
|
|
|
class _SCHomeSkeletonShimmerState extends State<SCHomeSkeletonShimmer>
|
|
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),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|