Skeleton Widget Without Any Package in Flutter
As much as everyone loves using packages for features because it makes our lives as software developers easy, it is also highly inconvenient at times because of the lack of control you have over the code, the headache of trying to change the user interface and most importantly, the added size it adds to your build. So sometimes it is much easier to make your own component.
In this article, we will be making a flutter skeleton or loader widget from scratch without using any external package or module.
Code:
skeleton.dart
import 'package:flutter/material.dart';
class Skeleton extends StatefulWidget {
final double height;
final double width;
final String type;
const Skeleton(
{super.key, this.height = 20, this.width = 20, this.type = 'square'});
@override
State<Skeleton> createState() => _SkeletonState();
}
class _SkeletonState extends State<Skeleton>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation gradientPosition;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 1500), vsync: this);
gradientPosition = Tween<double>(
begin: -3,
end: 10,
).animate(
CurvedAnimation(parent: _controller, curve: Curves.linear),
)..addListener(() {
setState(() {});
});
_controller.repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
decoration: BoxDecoration(
borderRadius: widget.type == 'circle'
? BorderRadius.circular(50)
: BorderRadius.circular(0),
gradient: LinearGradient(
begin: Alignment(gradientPosition.value, 0),
end: const Alignment(-1, 0),
colors: const [Colors.black12, Colors.black26, Colors.black12])),
);
}
}
It’s small and you have full control over the UI that you want to have. You can also give it a type circle param, to show the skeleton loader in a circle.
To use it:
Skeleton(height: 35, width: 35, type: 'circle')
Skeleton(height: 35, width: 35) // default is square
Feel free to leave any comments for improvement.