Creating an Animated Progress Button in Flutter

Animated Progress Button in Flutter

In this tutorial, we’ll learn how to create an animated progress button in Flutter. This button will transform into a loading indicator when pressed, providing a smooth and engaging user experience.

## Step 1: Create the AnimatedProgressButton Widget

First, we’ll create a custom widget called `AnimatedProgressButton`. This widget will handle the animation and state changes of our button.

This widget uses an `AnimatedContainer` to smoothly transition between the button and loading states. When `isLoading` is true, the button shrinks and displays a `CircularProgressIndicator`.

class AnimatedProgressButton extends StatelessWidget {
  final VoidCallback onPressed;
  final bool isLoading;
  final Widget child;

  const AnimatedProgressButton({
    Key? key,
    required this.onPressed,
    required this.isLoading,
    required this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      duration: const Duration(milliseconds: 300),
      width: isLoading ? 50 : 200,
      height: 50,
      child: ElevatedButton(
        onPressed: isLoading ? null : onPressed,
        style: ElevatedButton.styleFrom(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(30),
          ),
          padding: EdgeInsets.zero,
        ),
        child: Center(
          child: isLoading
              ? const SizedBox(
                  width: 30,
                  height: 30,
                  child: CircularProgressIndicator(
                    color: Colors.white,
                    strokeWidth: 2,
                  ),
                )
              : child,
        ),
      ),
    );
  }
}

## Step 2: Implement the Button in Your Page

Now, let’s see how to use this `AnimatedProgressButton` in a simple page.

full code:

import 'package:flutter/material.dart';

class NormalPage extends StatefulWidget {
  const NormalPage({Key? key}) : super(key: key);

  @override
  State<NormalPage> createState() => _NormalPageState();
}

class _NormalPageState extends State<NormalPage> {
  bool _isLoading = false;

  void _startLoading() {
    setState(() {
      _isLoading = true;
    });
    // Simulate a task
    Future.delayed(const Duration(seconds: 3), () {
      setState(() {
        _isLoading = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Animated Progress Button"),
        leading: IconButton(
          icon: const Icon(Icons.menu),
          onPressed: () {},
        ),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.comment),
            onPressed: () {},
          ), //IconButton
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () {},
          ), //IconButton
        ],
        elevation: 1,
      ),
      body: Center(
        child: AnimatedProgressButton(
          onPressed: _startLoading,
          isLoading: _isLoading,
          child: const Text('Submit'),
        ),
      ),
    );
  }
}

class AnimatedProgressButton extends StatelessWidget {
  final VoidCallback onPressed;
  final bool isLoading;
  final Widget child;

  const AnimatedProgressButton({
    Key? key,
    required this.onPressed,
    required this.isLoading,
    required this.child,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return AnimatedContainer(
      duration: const Duration(milliseconds: 300),
      width: isLoading ? 50 : 200,
      height: 50,
      child: ElevatedButton(
        onPressed: isLoading ? null : onPressed,
        style: ElevatedButton.styleFrom(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(30),
          ),
          padding: EdgeInsets.zero,
        ),
        child: Center(
          child: isLoading
              ? const SizedBox(
                  width: 30,
                  height: 30,
                  child: CircularProgressIndicator(
                    color: Colors.white,
                    strokeWidth: 2,
                  ),
                )
              : child,
        ),
      ),
    );
  }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注