Flutter Animation Stepper
A Flutter package for creating beautiful horizontal steppers with smooth animations and customizable themes.
Features
- Two Stepper Widgets:
AnimationStepper: Traditional stepper with icons, titles, and subtitlesMovingDotStepper: Minimal dot-based stepper with smooth transitions
- Smooth Animations: Elegant transitions between step states with customizable animation curves
- Fully Customizable: Control colors, sizes, fonts, and animation durations through theme
- Custom Icons: Support for custom icons in all states (inactive, active, completed) including SVG
- Loading Indicator: Built-in support for showing loading state on specific steps
- Step Navigation: Tap on steps to navigate with
onStepTappedcallback - Flexible Widgets: Support for any widget type in steps (Icon, Image, SVG, etc.)
- Layout Options: Choose between connected or separated line layouts
- Horizontal Scrolling: Automatically handles overflow with horizontal scrolling
Getting Started
Add this to your package's pubspec.yaml file:
dependencies:
flutter_animation_stepper: ^2.0.1
Then run:
flutter pub get
Usage
Basic Example
import 'package:flutter_animation_stepper/flutter_animation_stepper.dart';
AnimationStepper(
steps: [
StepItem(
icon: Icon(Icons.shopping_cart),
title: 'Cart',
subtitle: 'Review items',
),
StepItem(
icon: Icon(Icons.payment),
title: 'Payment',
subtitle: 'Enter details',
),
StepItem(
icon: Icon(Icons.check_circle),
title: 'Confirm',
subtitle: 'Complete order',
),
],
currentStep: 1,
onStepTapped: (index) {
setState(() => currentStep = index);
},
)
With Custom Theme
AnimationStepper(
steps: steps,
currentStep: currentStep,
theme: AnimationStepperTheme(
activeColor: Colors.blue,
completeColor: Colors.green,
inactiveColor: Colors.grey,
loadingColor: Colors.orange,
iconSize: 32,
lineHeight: 4,
),
onStepTapped: (index) {
setState(() => currentStep = index);
},
)
With Loading Indicator
AnimationStepper(
steps: steps,
currentStep: currentStep,
loadingStep: 1, // Show loading on step 1
onStepTapped: (index) {
setState(() => currentStep = index);
},
)
MovingDotStepper - Basic Usage
import 'package:flutter_animation_stepper/flutter_animation_stepper.dart';
// Steps are evenly distributed across the available width
// Control width using a parent Container or Expanded widget
Container(
width: 400, // Or use Expanded for flexible width
child: MovingDotStepper(
stepCount: 4,
currentStep: 1,
stepLabels: ['Start', 'Process', 'Review', 'Complete'],
onStepTapped: (index) {
setState(() => currentStep = index);
},
),
)
MovingDotStepper - With Custom Icons
Container(
width: double.infinity, // Fill available width
child: MovingDotStepper(
stepCount: 4,
currentStep: 1,
stepLabels: ['Start', 'Process', 'Review', 'Complete'],
inactiveIcon: Icon(Icons.radio_button_unchecked, color: Colors.grey, size: 16),
activeIcon: Icon(Icons.play_circle_filled, color: Colors.white, size: 16),
completedIcon: Icon(Icons.check_circle, color: Colors.white, size: 16),
theme: MovingDotStepperTheme(
activeColor: Colors.blue,
completedColor: Colors.green,
dotSize: 28.0,
lineInset: 4.0, // Optional: spacing between dots and lines
),
onStepTapped: (index) {
setState(() => currentStep = index);
},
),
)
MovingDotStepper - With SVG Icons
import 'package:flutter_svg/flutter_svg.dart';
Expanded(
child: MovingDotStepper(
stepCount: 3,
currentStep: 0,
inactiveIcon: SvgPicture.asset('assets/icons/inactive.svg', width: 16, height: 16),
activeIcon: SvgPicture.asset('assets/icons/active.svg', width: 16, height: 16),
completedIcon: SvgPicture.asset('assets/icons/completed.svg', width: 16, height: 16),
onStepTapped: (index) {
setState(() => currentStep = index);
},
),
)
MovingDotStepper - With Custom Dot Widgets
Replace the entire dot structure (not just the icon) with custom widgets:
Container(
width: 400,
child: MovingDotStepper(
stepCount: 4,
currentStep: 1,
stepLabels: ['Start', 'Process', 'Review', 'Complete'],
// Custom square dots instead of circles
completedDot: Container(
width: 28,
height: 28,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(4),
),
child: Icon(Icons.check, color: Colors.white, size: 16),
),
activeDot: Container(
width: 28,
height: 28,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(4),
),
child: Icon(Icons.edit, color: Colors.white, size: 16),
),
inactiveDot: Container(
width: 28,
height: 28,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(4),
border: Border.all(color: Colors.grey, width: 2),
),
),
onStepTapped: (index) {
setState(() => currentStep = index);
},
),
)
Additional Information
For more examples, check out the /example folder in the repository.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Issues
If you encounter any issues, please report them on GitHub Issues.
License
This project is licensed under the MIT License.