Loader 005 — Flutter Loader Widget

Free copy-paste Loader 005 for Flutter: a ready-to-use loader widget with full Dart source code and a live preview. Works on mobile & desktop. No external packages.

  • Category: Loadings
  • Platforms: mobile, desktop
  • Flutter SDK only — no external packages
  • Free to copy & use

How to use Loader 005 in Flutter

Copy the Dart code below into a new file in your Flutter project (for example lib/widgets/loader_005.dart) and use the widget anywhere in your widget tree.

Loader 005 – Dart source code

import 'package:flutter/material.dart';

class Loader005 extends StatefulWidget {
  const Loader005({
    super.key,
    this.width = 240.0,
    this.height = 130.0,
    this.cardColor = const Color(0xFFE3E3E3),
    this.borderColor = const Color(0xFFD3D3D3),
    this.blockColor = const Color(0xFFCACACA),
    this.duration = const Duration(milliseconds: 1000),
  });

  final double width;
  final double height;
  final Color cardColor;
  final Color borderColor;
  final Color blockColor;
  final Duration duration;

  @override
  State<Loader005> createState() => _Loader005State();
}

class _Loader005State extends State<Loader005>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this, duration: widget.duration)
      ..repeat();
  }

  @override
  void didUpdateWidget(covariant Loader005 oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.duration != widget.duration) {
      _controller.duration = widget.duration;
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      height: widget.height,
      clipBehavior: Clip.antiAlias,
      decoration: BoxDecoration(
        color: widget.cardColor,
        border: Border.all(color: widget.borderColor),
        borderRadius: BorderRadius.circular(4),
      ),
      padding: const EdgeInsets.all(15),
      child: Stack(
        children: [
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Container(
                    width: 50,
                    height: 50,
                    decoration: BoxDecoration(
                      color: widget.blockColor,
                      shape: BoxShape.circle,
                    ),
                  ),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Container(
                          height: 10,
                          width: 100,
                          decoration: BoxDecoration(
                            color: widget.blockColor,
                            borderRadius: BorderRadius.circular(2),
                          ),
                        ),
                        const SizedBox(height: 12),
                        Container(
                          height: 10,
                          width: double.infinity,
                          decoration: BoxDecoration(
                            color: widget.blockColor,
                            borderRadius: BorderRadius.circular(2),
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 13),
              Container(
                height: 10,
                width: double.infinity,
                decoration: BoxDecoration(
                  color: widget.blockColor,
                  borderRadius: BorderRadius.circular(2),
                ),
              ),
              const SizedBox(height: 13),
              FractionallySizedBox(
                widthFactor: 0.92,
                child: Container(
                  height: 10,
                  decoration: BoxDecoration(
                    color: widget.blockColor,
                    borderRadius: BorderRadius.circular(2),
                  ),
                ),
              ),
            ],
          ),
          Positioned.fill(
            child: AnimatedBuilder(
              animation: _controller,
              builder: (context, _) {
                return CustomPaint(
                  painter: _ShimmerPainter(progress: _controller.value),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

class _ShimmerPainter extends CustomPainter {
  const _ShimmerPainter({this.progress = 0.0});

  final double progress;

  @override
  void paint(Canvas canvas, Size size) {
    final double sweepWidth = size.width * 2.0;
    final double dx = -size.width + progress * sweepWidth;

    final rect = Rect.fromLTWH(0, 0, size.width, size.height);
    final paint = Paint()
      ..shader = LinearGradient(
        begin: Alignment.topLeft,
        end: Alignment.bottomRight,
        colors: const [
          Colors.transparent,
          Color(0x33FFFFFF),
          Color(0x66FFFFFF),
          Color(0x33FFFFFF),
          Colors.transparent,
        ],
        stops: const [0.0, 0.40, 0.50, 0.60, 1.0],
        transform: _SlideGradientTransform(dx / size.width),
      ).createShader(rect);

    canvas.drawRect(rect, paint);
  }

  @override
  bool shouldRepaint(_ShimmerPainter oldDelegate) =>
      oldDelegate.progress != progress;
}

class _SlideGradientTransform extends GradientTransform {
  const _SlideGradientTransform(this.slidePercent);

  final double slidePercent;

  @override
  Matrix4? transform(Rect bounds, {TextDirection? textDirection}) {
    return Matrix4.translationValues(bounds.width * slidePercent, 0.0, 0.0);
  }
}

More Flutter Loaders & Loading Animations