Animated Loading Button In Flutter

animated loading button in flutter fully customizable

How to Create a Custom Animated Loading Button in Flutter

In this tutorial, we’ll build a custom animated loading button in Flutter — perfect for handling async actions like login, form submission, or any network-related interaction. The button will animate between its normal and loading states with a smooth UI transition.

🚀 Final Output Preview

Watch the full implementation in this YouTube tutorial:

📦 Dependencies Used

Add these to your pubspec.yaml:

YAML

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8
  fluentui_system_icons: ^1.1.260
  loading_animation_widget: ^1.3.0
  google_fonts: ^6.2.1
  

🎨 Step 1: Create a Constants File

In Constants.dart, define your color palette:

YAML

const Color bluePurpleColor = Color(0xff5D5FEF);
const Color primaryColor = bluePurpleColor;
Color greyFont = const Color(0xff737791);
Color greenColor = const Color(0xff00E096);
// ... other colors ...
const Color backgroundColor = Color(0xffFAFBFC);
const Color headingColor = Color(0xff151D48);
  

🛠️ Step 2: CustomLoadingButton Widget (Full Code)

This reusable widget handles the animation and loading logic:

YAML

class _CustomLoadingButtonState extends State {
  bool isLoading = false;
  bool showText = true;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () async {
        setState(() {
          isLoading = true;
          showText = false;
        });
        await widget.onTap();
        setState(() => isLoading = false);
        Future.delayed(Duration(milliseconds: 100)).then((_) {
          setState(() => showText = true);
        });
      },
      child: AnimatedContainer(
        width: isLoading ? 60 : widget.width,
        height: widget.height,
        duration: Duration(milliseconds: 200),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(15),
          boxShadow: [
            BoxShadow(
              color: widget.isBorderButton
                  ? Colors.white
                  : primaryColor.withAlpha(50),
              blurRadius: 10,
              offset: Offset(0, 10),
            ),
          ],
          border: widget.isBorderButton
              ? Border.all(color: primaryColor)
              : null,
          color: widget.isBorderButton ? Colors.white : primaryColor,
        ),
        child: isLoading
            ? LoadingAnimationWidget.threeArchedCircle(
                color: widget.isBorderButton
                    ? primaryColor
                    : Colors.white,
                size: 35,
              )
            : Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  if (widget.icon != null)
                    Icon(
                      widget.icon,
                      color: widget.isBorderButton
                          ? primaryColor
                          : Colors.white,
                    ),
                  if (widget.icon != null) SizedBox(width: 8),
                  if (showText)
                    Text(
                      widget.title,
                      style: GoogleFonts.poppins(
                        fontWeight: FontWeight.w600,
                        color: widget.isBorderButton
                            ? primaryColor
                            : Colors.white,
                      ),
                    ),
                ],
              ),
      ),
    );
  }
}
  

Make sure to include this inside the CustomLoadingButton widget from the previous step.

🧪 Step 3: Using the Button

In HomeScreen.dart, simply use the widget like this:

YAML

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: CustomLoadingButton(
            isBorderButton: true,
            title: 'Click Me',
            icon: FluentIcons.checkmark_circle_20_regular,
            onTap: () async {
              await Future.delayed(Duration(seconds: 1));
            },
          ),
        ),
      ),
    );
  }
}
  

✅ Features

  • Animated transition between text and loader

  • Optional border style

  • Optional leading icon

  • Reusable and customizable

📁 Folder Structure (Simplified)

lib/

├── Constants.dart
├── Widgets/
│ └── CustomLoadingButton.dart
└── HomeScreen.dart

🎉 Conclusion

You now have a fully customizable animated loading button in Flutter! This UI pattern is a fantastic way to improve the user experience for async actions.

Leave a Reply

Your email address will not be published. Required fields are marked *