Loader 009 — Flutter Loader Widget

Free copy-paste Loader 009 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 009 in Flutter

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

Loader 009 – Dart source code

import 'package:flutter/material.dart';

class Loader009 extends StatefulWidget {
  const Loader009({
    super.key,
    this.width = 45.0,
    this.height = 40.0,
    this.color = Colors.white,
    this.blockWidth = 10.0,
    this.blockHeight = 14.0,
    this.duration = const Duration(milliseconds: 1000),
  });

  final double width;
  final double height;
  final Color color;
  final double blockWidth;
  final double blockHeight;
  final Duration duration;

  @override
  State<Loader009> createState() => _Loader009State();
}

class _Loader009State extends State<Loader009>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;

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

  @override
  void didUpdateWidget(covariant Loader009 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 SizedBox(
      width: widget.width,
      height: widget.height,
      child: AnimatedBuilder(
        animation: _controller,
        builder: (context, _) {
          return CustomPaint(
            painter: _MatrixPainter(
              progress: _controller.value,
              color: widget.color,
              blockWidth: widget.blockWidth,
              blockHeight: widget.blockHeight,
            ),
          );
        },
      ),
    );
  }
}

class _MatrixPainter extends CustomPainter {
  const _MatrixPainter({
    this.progress = 0.0,
    this.color = Colors.white,
    this.blockWidth = 10.0,
    this.blockHeight = 14.0,
  });

  final double progress;
  final Color color;
  final double blockWidth;
  final double blockHeight;

  @override
  void paint(Canvas canvas, Size size) {
    canvas.clipRect(Offset.zero & size);

    final paint = Paint()
      ..color = color
      ..style = PaintingStyle.fill;

    final double colGap = (size.width - 3 * blockWidth) / 2;
    final double cycleHeight = size.height + blockHeight;

    for (int col = 0; col < 3; col++) {
      final double x = col * (blockWidth + colGap);
      final double offset = col * (1.0 / 3.0);
      final double normT = (progress + offset) % 1.0;

      final double y1 = size.height - (normT * cycleHeight);
      final double y2 = y1 + cycleHeight;

      final r1 = RRect.fromRectAndRadius(
        Rect.fromLTWH(x, y1, blockWidth, blockHeight),
        Radius.circular(blockWidth / 4),
      );
      canvas.drawRRect(r1, paint);

      if (y1 < 0) {
        final r2 = RRect.fromRectAndRadius(
          Rect.fromLTWH(x, y2, blockWidth, blockHeight),
          Radius.circular(blockWidth / 4),
        );
        canvas.drawRRect(r2, paint);
      }
    }
  }

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

More Flutter Loaders & Loading Animations