animated_wizard_bar
Animated Wizard Bar is a highly customizable Flutter package that provides a sleek and engaging way to build wizard-like multi-step user interfaces. With smooth animations, dynamic step indicators, and intuitive navigation controls, this package simplifies the process of creating interactive forms, onboarding flows, or any multi-step UI.
preview



Features
- animated wizard bar with page view.
- Customizable colors for selected and unselected icons.
- Customizable indicator and item decorations.
- Animated step indicators with customizable icons and styles.
- Horizontal wizard bar with scrolling capabilities.
- Flexible API for controlling navigation between steps.
- Supports dynamic content for each step in the wizard.
- Built-in animations for transitions and scale effects.
- Lightweight and easy to integrate into any Flutter project.
Getting started
This plugin is in beta, We are working on it to improve it.
Install
In the pubspec.yaml
of your flutter project, add the following dependency:
dependencies:
animated_wizard_bar: <latest_version>
Usage
first of all you have to write this code in your main dart file :
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
import 'package:animated_wizard_bar/custom_page_view_screen.dart';
import 'package:animated_wizard_bar/page_view/custom_page_viewmodel.dart';
import 'package:animated_wizard_bar/page_view/wizrdbar_viewmodel.dart';
import 'package:flutter_tabler_icons/flutter_tabler_icons.dart';
import 'package:animated_wizard_bar/page_view/widgets/custom_page_view_package.dart';
import 'package:animated_wizard_bar/page_view/widgets/step_horizontal_animation.dart';
import 'package:animated_wizard_bar/page_view/widgets/wizardbar_animation.dart';
void main() {
runApp(multiProvider);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: const WizardExample(),
);
}
}
List<SingleChildWidget> providers = [
ChangeNotifierProvider<CustomPageViewModel>(
create: (context) => CustomPageViewModel(),
),
ChangeNotifierProvider<WizardBarViewModel>(
create: (context) => WizardBarViewModel(),
),
];
MultiProvider multiProvider = MultiProvider(providers: providers, child: const MyApp());
in class you want use animated wizard bar package
class ExampleWizard extends StatefulWidget {
const ExampleWizard({
super.key,
});
@override
State<ExampleWizard> createState() => _ExampleWizardState();
}
class _ExampleWizardState extends State<ExampleWizard> with TickerProviderStateMixin {
final singleChildScrollControllerWizardBar = ScrollController();
here you have to create instance of global key for your StepHorizontalAnimation widgets and after that create list
var key1 = GlobalKey();
var key2 = GlobalKey();
var key3 = GlobalKey();
var key4 = GlobalKey();
var key5 = GlobalKey();
List<Animation<double>> animationList = [];
List<AnimationController> aniControllerList = [];
List<Widget> pageViewList = [
Container(
color: Colors.amber,
child: const Center(
child: Text('0'),
),
),
const Center(
child: Text('1'),
),
const Center(
child: Text('2'),
),
const Center(
child: Text('3'),
),
const Center(
child: Text('4'),
),
// const Center(
// child: Text('5'),
// )
];
in init state of your class you must animation controller list for youe StepHorizontalAnimation widgets .
@override
void initState() {
// Initialize animation controllers with the same configuration.
aniControllerList = List.generate(
// 5 is number of animation controller you want generated
5,
(_) => AnimationController(
vsync: this, // Provides the Ticker for animations.
duration: const Duration(milliseconds: 800), // Forward animation duration.
reverseDuration: const Duration(milliseconds: 800), // Reverse animation duration.
)..addListener(() {}), // Listener can be used for additional behavior.
);
// Create scale animations for each step using the animation controllers.
animationList = aniControllerList.asMap().entries.map((entry) {
int index = entry.key;
AnimationController controller = entry.value;
if (index == 0) {
return Tween<double>(begin: 0.95, end: 1.35).animate(controller);
} else {
return Tween<double>(begin: 1.35, end: 0.95).animate(controller);
}
}).toList();
// Start all animations in the forward direction.
for (var controller in aniControllerList) {
controller.forward();
}
super.initState();
}
here you must create instance list of StepHorizontalAnimation :
pay Attention :
The length of the steps list must be equal to the length of the pageViewList.
@override
Widget build(BuildContext context) {
List<StepHorizontalAnimation> stepsList = [
StepHorizontalAnimation(
filled: true,
boxKey: key1,
icon: TablerIcons.user,
visibleLeft: true,
itemsNeedForFilled: 9,
stepsNumber: 0,
scaleAnimation: animationList.elementAt(0),
scaleAnimationList: aniControllerList,
scrollController: singleChildScrollControllerWizardBar,
canSelect: false,
// enable: true,
),
StepHorizontalAnimation(
filled: false,
boxKey: key2,
icon: TablerIcons.home_check,
visibleLeft: true,
itemsNeedForFilled: 7,
stepsNumber: 1,
scaleAnimation: animationList.elementAt(1),
scaleAnimationList: aniControllerList,
scrollController: singleChildScrollControllerWizardBar,
canSelect: false,
// enable: true,
),
StepHorizontalAnimation(
filled: false,
boxKey: key3,
icon: TablerIcons.briefcase,
visibleLeft: true,
itemsNeedForFilled: 10,
stepsNumber: 2,
scaleAnimation: animationList.elementAt(2),
scaleAnimationList: aniControllerList,
scrollController: singleChildScrollControllerWizardBar,
canSelect: true,
// enable: true,
),
StepHorizontalAnimation(
filled: false,
boxKey: key4,
icon: TablerIcons.users,
visibleLeft: true,
itemsNeedForFilled: 13,
stepsNumber: 3,
scaleAnimation: animationList.elementAt(3),
scaleAnimationList: aniControllerList,
scrollController: singleChildScrollControllerWizardBar,
canSelect: false,
// enable: true,
),
StepHorizontalAnimation(
filled: false,
boxKey: key5,
icon: TablerIcons.building_store,
visibleLeft: false,
itemsNeedForFilled: 1,
stepsNumber: 4,
scaleAnimation: animationList.elementAt(4),
scaleAnimationList: aniControllerList,
scrollController: singleChildScrollControllerWizardBar,
canSelect: false,
// enable: true,
),
];
final getCustomPageViewModel = Provider.of<CustomPageViewModel>(context, listen: false);
return WillPopScope(
onWillPop: () async {
if (getCustomPageViewModel.currentLevel == 0) {
return true;
} else {
getCustomPageViewModel.previousPage(aniControllerList, singleChildScrollControllerWizardBar, stepsList.length, stepsList[getCustomPageViewModel.currentLevel].boxKey);
return false;
}
},
child: SafeArea(
child: Scaffold(
body: CustomPageView(
appBar: AppBar(
title: const Text(
'animated wizard bar',
),
centerTitle: true,
),
pageViewItems: pageViewList,
aniController: aniControllerList,
stepsList: stepsList,
singleChildScrollController: singleChildScrollControllerWizardBar,
wizardBarAnimation: WizardBarAnimation(singleChildScrollControllerWizardBar, stepsList),
),
),
),
);
}
}
https://github.com/matinsoleymani/animated_wizard_stepper/tree/sprint_01?tab=readme-ov-file
Documentation
Classes
- CustomPageView: Core widget that renders the wizard UI.
- StepHorizontalAnimation: Handles the animation for step indicators.
- WizardBarAnimation: Manages the horizontal wizard bar.
Methods
- previousPage: Navigate to the previous step.
- nextPage: Navigate to the next step.
Contributing
Contributions are welcome! If you have suggestions, bug reports, or feature requests, feel free to open an issue or submit a pull request on https://github.com/matinsoleymani/animated_wizard_stepper.
connect with me on LinkedIn