how to create a toggle button with animation in flutter

flutter toggle button animation

We’ll create a custom animated toggle button that switches between two states with a smooth animation.

  1. We’ve added SingleTickerProviderStateMixin to the _NormalPageState class to use an AnimationController.
  2. We’ve introduced an AnimationController and a boolean _isToggled to manage the toggle state and animation.
  3. The initState() method initializes the AnimationController, and dispose() cleans it up.
    We’ve added a _toggleButton() method to handle the toggle state and animation.
  4. In the build() method, we’ve replaced the empty Container with a Center widget containing our new AnimatedToggle and a Text widget to display the current toggle state.

full code, just copy and run:

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> with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  bool _isToggled = false;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
  }

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

  void _toggleButton() {
    setState(() {
      _isToggled = !_isToggled;
      if (_isToggled) {
        _animationController.forward();
      } else {
        _animationController.reverse();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("This is a title"),
        leading: IconButton(
          icon: const Icon(Icons.menu),
          onPressed: () {},
        ),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.comment),
            onPressed: () {},
          ),
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () {},
          ),
        ],
        elevation: 1,
      ),
      body: Material(
        child: SafeArea(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                AnimatedToggle(
                  animationController: _animationController,
                  onToggle: _toggleButton,
                ),
                const SizedBox(height: 20),
                Text(
                  _isToggled ? 'Toggled On' : 'Toggled Off',
                  style: const TextStyle(fontSize: 18),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class AnimatedToggle extends StatelessWidget {
  final AnimationController animationController;
  final VoidCallback onToggle;

  const AnimatedToggle({
    Key? key,
    required this.animationController,
    required this.onToggle,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onToggle,
      child: AnimatedBuilder(
        animation: animationController,
        builder: (context, child) {
          return Container(
            width: 70,
            height: 40,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(20),
              color: Color.lerp(Colors.grey[300], Colors.blue, animationController.value),
            ),
            child: Padding(
              padding: const EdgeInsets.all(4),
              child: Stack(
                children: [
                  Positioned(
                    left: animationController.value * 30,
                    child: Container(
                      width: 32,
                      height: 32,
                      decoration: const BoxDecoration(
                        shape: BoxShape.circle,
                        color: Colors.white,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}

发表回复

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