mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
feat: static shimmer for track tile, playbutton card and track tile
This commit is contained in:
parent
69995bea1c
commit
3ed8b0fda2
@ -20,25 +20,22 @@ class ShimmerCategories extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Container(
|
||||||
padding: const EdgeInsets.only(left: 15),
|
padding: const EdgeInsets.only(left: 15),
|
||||||
child: SkeletonAnimation(
|
height: 10,
|
||||||
shimmerColor: shimmerBackgroundColor,
|
width: 100,
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
shimmerDuration: 1000,
|
|
||||||
child: Container(
|
|
||||||
width: 150,
|
|
||||||
height: 15,
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: shimmerColor,
|
color: shimmerBackgroundColor,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
margin: const EdgeInsets.only(top: 10),
|
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
const Align(
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
child: ShimmerPlaybuttonCard(count: 7),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const ShimmerPlaybuttonCard(count: 7),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,89 +1,161 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:skeleton_text/skeleton_text.dart';
|
|
||||||
import 'package:spotube/extensions/ShimmerColorTheme.dart';
|
import 'package:spotube/extensions/ShimmerColorTheme.dart';
|
||||||
|
|
||||||
|
class ShimmerPlaybuttonCardPainter extends CustomPainter {
|
||||||
|
final Color background;
|
||||||
|
final Color foreground;
|
||||||
|
ShimmerPlaybuttonCardPainter({
|
||||||
|
required this.background,
|
||||||
|
required this.foreground,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromRectAndRadius(
|
||||||
|
Rect.fromLTWH(0, 0, size.width, size.height),
|
||||||
|
const Radius.circular(10),
|
||||||
|
),
|
||||||
|
Paint()..color = background,
|
||||||
|
);
|
||||||
|
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromRectAndRadius(
|
||||||
|
Rect.fromLTWH(0, 0, size.width, size.height - 45),
|
||||||
|
const Radius.circular(10),
|
||||||
|
),
|
||||||
|
Paint()..color = foreground,
|
||||||
|
);
|
||||||
|
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromRectAndRadius(
|
||||||
|
Rect.fromLTWH(size.width / 4, size.height - 27, size.width / 2, 10),
|
||||||
|
const Radius.circular(10),
|
||||||
|
),
|
||||||
|
Paint()..color = foreground,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ShimmerPlaybuttonCard extends StatelessWidget {
|
class ShimmerPlaybuttonCard extends StatelessWidget {
|
||||||
final int count;
|
final int count;
|
||||||
const ShimmerPlaybuttonCard({Key? key, this.count = 4}) : super(key: key);
|
|
||||||
|
const ShimmerPlaybuttonCard({
|
||||||
|
Key? key,
|
||||||
|
this.count = 1,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final shimmerColor =
|
final shimmerTheme = Theme.of(context).extension<ShimmerColorTheme>();
|
||||||
Theme.of(context).extension<ShimmerColorTheme>()?.shimmerColor ??
|
|
||||||
Colors.white;
|
|
||||||
final shimmerBackgroundColor = Theme.of(context)
|
|
||||||
.extension<ShimmerColorTheme>()
|
|
||||||
?.shimmerBackgroundColor ??
|
|
||||||
Colors.grey;
|
|
||||||
|
|
||||||
final card = Stack(
|
return Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
SkeletonAnimation(
|
for (var i = 0; i < count; i++) ...[
|
||||||
shimmerColor: shimmerColor,
|
CustomPaint(
|
||||||
borderRadius: BorderRadius.circular(20),
|
size: const Size(200, 250),
|
||||||
shimmerDuration: 1000,
|
painter: ShimmerPlaybuttonCardPainter(
|
||||||
child: Container(
|
background: shimmerTheme?.shimmerBackgroundColor ??
|
||||||
width: 200,
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
height: 220,
|
foreground:
|
||||||
decoration: BoxDecoration(
|
shimmerTheme?.shimmerColor ?? Theme.of(context).cardColor,
|
||||||
color: shimmerBackgroundColor,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(top: 10),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
SkeletonAnimation(
|
|
||||||
shimmerColor: shimmerBackgroundColor,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
shimmerDuration: 1000,
|
|
||||||
child: Container(
|
|
||||||
width: 200,
|
|
||||||
height: 180,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: shimmerColor,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(top: 10),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
SkeletonAnimation(
|
|
||||||
shimmerColor: shimmerBackgroundColor,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
shimmerDuration: 1000,
|
|
||||||
child: Container(
|
|
||||||
width: 150,
|
|
||||||
height: 10,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: shimmerColor,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(top: 10),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
]
|
||||||
],
|
],
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
return SingleChildScrollView(
|
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: List.generate(
|
|
||||||
count,
|
|
||||||
(_) => Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
|
||||||
child: card,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class ShimmerPlaybuttonCard extends StatelessWidget {
|
||||||
|
// final int count;
|
||||||
|
// const ShimmerPlaybuttonCard({Key? key, this.count = 4}) : super(key: key);
|
||||||
|
|
||||||
|
// @override
|
||||||
|
// Widget build(BuildContext context) {
|
||||||
|
// final shimmerColor =
|
||||||
|
// Theme.of(context).extension<ShimmerColorTheme>()?.shimmerColor ??
|
||||||
|
// Colors.white;
|
||||||
|
// final shimmerBackgroundColor = Theme.of(context)
|
||||||
|
// .extension<ShimmerColorTheme>()
|
||||||
|
// ?.shimmerBackgroundColor ??
|
||||||
|
// Colors.grey;
|
||||||
|
|
||||||
|
// final card = Stack(
|
||||||
|
// children: [
|
||||||
|
// SkeletonAnimation(
|
||||||
|
// shimmerColor: shimmerColor,
|
||||||
|
// borderRadius: BorderRadius.circular(20),
|
||||||
|
// shimmerDuration: 1000,
|
||||||
|
// child: Container(
|
||||||
|
// width: 200,
|
||||||
|
// height: 220,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: shimmerBackgroundColor,
|
||||||
|
// borderRadius: BorderRadius.circular(10),
|
||||||
|
// ),
|
||||||
|
// margin: const EdgeInsets.only(top: 10),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// Column(
|
||||||
|
// children: [
|
||||||
|
// SkeletonAnimation(
|
||||||
|
// shimmerColor: shimmerBackgroundColor,
|
||||||
|
// borderRadius: BorderRadius.circular(20),
|
||||||
|
// shimmerDuration: 1000,
|
||||||
|
// child: Container(
|
||||||
|
// width: 200,
|
||||||
|
// height: 180,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: shimmerColor,
|
||||||
|
// borderRadius: BorderRadius.circular(10),
|
||||||
|
// ),
|
||||||
|
// margin: const EdgeInsets.only(top: 10),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(height: 5),
|
||||||
|
// SkeletonAnimation(
|
||||||
|
// shimmerColor: shimmerBackgroundColor,
|
||||||
|
// borderRadius: BorderRadius.circular(20),
|
||||||
|
// shimmerDuration: 1000,
|
||||||
|
// child: Container(
|
||||||
|
// width: 150,
|
||||||
|
// height: 10,
|
||||||
|
// decoration: BoxDecoration(
|
||||||
|
// color: shimmerColor,
|
||||||
|
// borderRadius: BorderRadius.circular(10),
|
||||||
|
// ),
|
||||||
|
// margin: const EdgeInsets.only(top: 10),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// );
|
||||||
|
|
||||||
|
// return SingleChildScrollView(
|
||||||
|
// physics: const NeverScrollableScrollPhysics(),
|
||||||
|
// scrollDirection: Axis.horizontal,
|
||||||
|
// child: Row(
|
||||||
|
// children: [
|
||||||
|
// Row(
|
||||||
|
// children: List.generate(
|
||||||
|
// count,
|
||||||
|
// (_) => Padding(
|
||||||
|
// padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||||
|
// child: card,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
@ -1,95 +1,107 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:skeleton_text/skeleton_text.dart';
|
|
||||||
import 'package:spotube/extensions/ShimmerColorTheme.dart';
|
import 'package:spotube/extensions/ShimmerColorTheme.dart';
|
||||||
|
|
||||||
|
class ShimmerTrackTilePainter extends CustomPainter {
|
||||||
|
final Color background;
|
||||||
|
final Color foreground;
|
||||||
|
ShimmerTrackTilePainter({
|
||||||
|
required this.background,
|
||||||
|
required this.foreground,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
final paint = Paint()
|
||||||
|
..color = background
|
||||||
|
..style = PaintingStyle.fill;
|
||||||
|
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromRectAndRadius(
|
||||||
|
Rect.fromLTWH(0, 0, size.width, size.height),
|
||||||
|
const Radius.circular(5),
|
||||||
|
),
|
||||||
|
paint,
|
||||||
|
);
|
||||||
|
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromRectAndRadius(
|
||||||
|
const Rect.fromLTWH(5, 5, 40, 40),
|
||||||
|
const Radius.circular(5),
|
||||||
|
),
|
||||||
|
Paint()..color = foreground,
|
||||||
|
);
|
||||||
|
|
||||||
|
canvas.drawCircle(
|
||||||
|
const Offset(70, 25),
|
||||||
|
15,
|
||||||
|
Paint()..color = foreground,
|
||||||
|
);
|
||||||
|
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromRectAndRadius(
|
||||||
|
const Rect.fromLTWH(95, 10, 100, 10),
|
||||||
|
const Radius.circular(5),
|
||||||
|
),
|
||||||
|
Paint()..color = foreground,
|
||||||
|
);
|
||||||
|
|
||||||
|
canvas.drawRRect(
|
||||||
|
RRect.fromRectAndRadius(
|
||||||
|
const Rect.fromLTWH(95, 30, 170, 7),
|
||||||
|
const Radius.circular(5),
|
||||||
|
),
|
||||||
|
Paint()..color = foreground,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ShimmerTrackTile extends StatelessWidget {
|
class ShimmerTrackTile extends StatelessWidget {
|
||||||
final bool noSliver;
|
final bool noSliver;
|
||||||
|
const ShimmerTrackTile({super.key, this.noSliver = false});
|
||||||
const ShimmerTrackTile({
|
|
||||||
Key? key,
|
|
||||||
this.noSliver = false,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final shimmerColor =
|
final shimmerTheme = Theme.of(context).extension<ShimmerColorTheme>();
|
||||||
Theme.of(context).extension<ShimmerColorTheme>()?.shimmerColor ??
|
|
||||||
Colors.white;
|
|
||||||
final shimmerBackgroundColor = Theme.of(context)
|
|
||||||
.extension<ShimmerColorTheme>()
|
|
||||||
?.shimmerBackgroundColor ??
|
|
||||||
Colors.grey;
|
|
||||||
|
|
||||||
final single = Container(
|
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 20),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
SkeletonAnimation(
|
|
||||||
shimmerColor: shimmerColor,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
shimmerDuration: 1000,
|
|
||||||
child: Container(
|
|
||||||
width: 50,
|
|
||||||
height: 50,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: shimmerBackgroundColor,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(top: 10),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
SkeletonAnimation(
|
|
||||||
shimmerColor: shimmerColor,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
shimmerDuration: 1000,
|
|
||||||
child: Container(
|
|
||||||
height: 15,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: shimmerBackgroundColor,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(top: 10),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SkeletonAnimation(
|
|
||||||
shimmerColor: shimmerColor,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
shimmerDuration: 1000,
|
|
||||||
child: Container(
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
maxWidth: MediaQuery.of(context).size.width * .8),
|
|
||||||
height: 10,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: shimmerBackgroundColor,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(top: 10),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (noSliver) {
|
if (noSliver) {
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
shrinkWrap: true,
|
|
||||||
itemCount: 5,
|
itemCount: 5,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
itemBuilder: (context, index) {
|
||||||
itemBuilder: (context, _) => single,
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8.0, left: 8, right: 8),
|
||||||
|
child: CustomPaint(
|
||||||
|
size: const Size(double.infinity, 50),
|
||||||
|
painter: ShimmerTrackTilePainter(
|
||||||
|
background: shimmerTheme?.shimmerBackgroundColor ??
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foreground:
|
||||||
|
shimmerTheme?.shimmerColor ?? Theme.of(context).cardColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SliverList(
|
return SliverList(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(BuildContext context, int index) => single,
|
(BuildContext context, int index) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8.0, left: 8, right: 8),
|
||||||
|
child: CustomPaint(
|
||||||
|
size: const Size(double.infinity, 50),
|
||||||
|
painter: ShimmerTrackTilePainter(
|
||||||
|
background: shimmerTheme?.shimmerBackgroundColor ??
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foreground:
|
||||||
|
shimmerTheme?.shimmerColor ?? Theme.of(context).cardColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
childCount: 5,
|
childCount: 5,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user