1import 'package:flutter/material.dart';
2
3class SkeletonTimeline extends StatelessWidget {
4 final int itemCount;
5 final bool useSliver;
6 final EdgeInsetsGeometry padding;
7 const SkeletonTimeline({
8 super.key,
9 this.itemCount = 6,
10 this.useSliver = false,
11 this.padding = const EdgeInsets.symmetric(vertical: 24, horizontal: 8),
12 });
13
14 @override
15 Widget build(BuildContext context) {
16 if (useSliver) {
17 return SliverPadding(
18 padding: padding,
19 sliver: SliverList(
20 delegate: SliverChildBuilderDelegate(
21 (context, index) => _buildSkeletonItem(context, index),
22 childCount: itemCount,
23 ),
24 ),
25 );
26 } else {
27 return ListView.builder(
28 itemCount: itemCount,
29 padding: padding,
30 itemBuilder: (context, index) => _buildSkeletonItem(context, index),
31 );
32 }
33 }
34
35 Widget _buildSkeletonItem(BuildContext context, int index) {
36 final theme = Theme.of(context);
37 final Color skeletonColor = theme.colorScheme.surfaceContainerHighest.withAlpha(128);
38 final double fade = 1.0 - (index / itemCount) * 0.3;
39 final Color fadedColor = skeletonColor.withOpacity(fade);
40
41 return Padding(
42 padding: const EdgeInsets.only(bottom: 24),
43 child: Column(
44 crossAxisAlignment: CrossAxisAlignment.start,
45 children: [
46 Row(
47 children: [
48 Container(
49 width: 36,
50 height: 36,
51 decoration: BoxDecoration(color: fadedColor, shape: BoxShape.circle),
52 ),
53 const SizedBox(width: 10),
54 Expanded(
55 child: Column(
56 crossAxisAlignment: CrossAxisAlignment.start,
57 children: [
58 Container(height: 14, width: 120, color: fadedColor),
59 const SizedBox(height: 6),
60 Container(height: 12, width: 80, color: fadedColor),
61 ],
62 ),
63 ),
64 Container(height: 12, width: 40, color: fadedColor),
65 ],
66 ),
67 const SizedBox(height: 12),
68 Container(
69 height: 180,
70 width: double.infinity,
71 color: fadedColor,
72 margin: const EdgeInsets.symmetric(horizontal: 2),
73 ),
74 const SizedBox(height: 12),
75 Container(
76 height: 16,
77 width: 160,
78 color: fadedColor,
79 margin: const EdgeInsets.only(left: 2),
80 ),
81 const SizedBox(height: 8),
82 Container(
83 height: 12,
84 width: double.infinity,
85 color: fadedColor,
86 margin: const EdgeInsets.only(left: 2),
87 ),
88 const SizedBox(height: 16),
89 Row(
90 children: List.generate(
91 3,
92 (i) => Padding(
93 padding: const EdgeInsets.only(right: 12),
94 child: Container(
95 width: 32,
96 height: 32,
97 decoration: BoxDecoration(
98 color: fadedColor,
99 borderRadius: BorderRadius.circular(8),
100 ),
101 ),
102 ),
103 ),
104 ),
105 ],
106 ),
107 );
108 }
109}