We’ll create a custom animated toggle button that switches between two states with a smooth animation.
- We’ve added SingleTickerProviderStateMixin to the _NormalPageState class to use an AnimationController.
- We’ve introduced an AnimationController and a boolean _isToggled to manage the toggle state and animation.
- The initState() method initializes the AnimationController, and dispose() cleans it up.
We’ve added a _toggleButton() method to handle the toggle state and animation. - 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, ), ), ), ], ), ), ); }, ), ); } }