Loader 004 — Flutter Loader Widget

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

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

Loader 004 – Dart source code

import 'dart:math' as math;

import 'package:flutter/material.dart';

class Loader004 extends StatefulWidget {
  const Loader004({
    super.key,
    this.size = 48.0,
    this.dotSize = 18.0,
    this.color = const Color(0xFF333333),
    this.duration = const Duration(milliseconds: 1000),
  });

  final double size;
  final double dotSize;
  final Color color;
  final Duration duration;

  @override
  State<Loader004> createState() => _Loader004State();
}

class _Loader004State extends State<Loader004>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;

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

  @override
  void didUpdateWidget(covariant Loader004 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) {
    final s = widget.size;
    final d = widget.dotSize;

    return AnimatedBuilder(
      animation: _controller,
      builder: (context, _) {
        final t = _controller.value;
        final angle = t * 2 * math.pi;
        final scale = 1.0 + 0.3 * math.sin(t * 2 * math.pi).abs();

        return Transform.scale(
          scale: scale,
          child: Transform.rotate(
            angle: angle,
            child: SizedBox(
              width: s,
              height: s,
              child: Stack(
                children: [
                  Positioned(
                    top: 0,
                    left: 0,
                    child: _Dot(size: d, color: widget.color),
                  ),
                  Positioned(
                    top: 0,
                    right: 0,
                    child: _Dot(size: d, color: widget.color),
                  ),
                  Positioned(
                    bottom: 0,
                    left: 0,
                    child: _Dot(size: d, color: widget.color),
                  ),
                  Positioned(
                    bottom: 0,
                    right: 0,
                    child: _Dot(size: d, color: widget.color),
                  ),
                ],
              ),
            ),
          ),
        );
      },
    );
  }
}

class _Dot extends StatelessWidget {
  const _Dot({this.size = 18.0, this.color = const Color(0xFF333333)});

  final double size;
  final Color color;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: size,
      height: size,
      decoration: BoxDecoration(color: color, shape: BoxShape.circle),
    );
  }
}

More Flutter Loaders & Loading Animations