Flutter Stepper Widget Example
In this article, Beginners can learn how to use flutter stepper widget in flutter applications. Stepper widget is used to divide large form into sections so users can easily understand.
In this example, We will use simple information form to integrate flutter stepper widget. We will display three steps to user to fill the form.
In first step, User can add his personal info like name, date of birth and gender. In second step, User need to fill his contact information like email, home address and mobile no. Now all filled details will be displayed in third step so user can confirm before submit it.
Add steps in array
First we need to add step widget in step type array. Step widget provides different types of parameters. title parameter is used to display step title. You can set your custom layout in content parameter for specific step.
state parameter is used to assign state to step widget from many states like editing, indexed, complete. We assign step state to indexed by default. Whenever we reaches to specific step then we change their state from indexed to editing. In this example, We will not edit any info in final step so we assign complete state to final step.
Step(
title: Text(‘Personal’),
content: Personal(),
state: currentStep == 0 ? StepState.editing : StepState.indexed,
isActive: true,
),
Step(
title: Text(‘Contact’),
content: Contact(),
state: currentStep == 1 ? StepState.editing : StepState.indexed,
isActive: true,
),
Step(
title: Text(‘Upload’),
content: Upload(),
state: StepState.complete,
isActive: true,
),
];
Add flutter stepper widget
We must add our array to steps parameter in Flutter Stepper widget. We can also display steps in horizontal or vertical direction with the help of type parameter. onStepTapped method is used to detect click on step header. You can also display step layout on click of step header.
You can also set actions on click of continue and cancel buttons using onStepContinue and onStepCancel parameters. We bring user to previous step on click of cancel button and to next step on click of continue button.
currentStep: this.currentStep,
steps: steps,
type: StepperType.horizontal,
onStepTapped: (step) {
setState(() {
currentStep = step;
});
},
onStepContinue: () {
setState(() {
if (currentStep < steps.length – 1) {
if (currentStep == 0) {
currentStep = currentStep + 1;
} else if (currentStep == 1) {
currentStep = currentStep + 1;
}
} else {
currentStep = 0;
}
});
},
onStepCancel: () {
setState(() {
if (currentStep > 0) {
currentStep = currentStep – 1;
} else {
currentStep = 0;
}
});
},
),
Final Code
main.dart
import 'dart:collection'; import 'package:flutter/material.dart'; import 'contact.dart'; import 'personal.dart'; import 'upload.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: FlutterStepperPage(title: 'Flutter Stepper Sample'), ); } } class FlutterStepperPage extends StatefulWidget { FlutterStepperPage({Key key, this.title}) : super(key: key); final String title; @override _FlutterStepperPageState createState() => _FlutterStepperPageState(); } class _FlutterStepperPageState extends State<FlutterStepperPage> { var currentStep = 0; @override Widget build(BuildContext context) { var mapData = HashMap<String, String>(); mapData["first_name"] = PersonalState.controllerFirstName.text; mapData["last_name"] = PersonalState.controllerLastName.text; mapData["date_of_birth"] = PersonalState.controllerDateOfBirth.text; mapData["gender"] = PersonalState.controllerGender.text; mapData["email"] = ContactState.controllerEmail.text; mapData["address"] = ContactState.controllerAddress.text; mapData["mobile_no"] = ContactState.controllerMobileNo.text; List<Step> steps = [ Step( title: Text('Personal'), content: Personal(), state: currentStep == 0 ? StepState.editing : StepState.indexed, isActive: true, ), Step( title: Text('Contact'), content: Contact(), state: currentStep == 1 ? StepState.editing : StepState.indexed, isActive: true, ), Step( title: Text('Upload'), content: Upload(mapData), state: StepState.complete, isActive: true, ), ]; return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Container( child: Stepper( currentStep: this.currentStep, steps: steps, type: StepperType.horizontal, onStepTapped: (step) { setState(() { currentStep = step; }); }, onStepContinue: () { setState(() { if (currentStep < steps.length - 1) { if (currentStep == 0 && PersonalState.formKey.currentState.validate()) { currentStep = currentStep + 1; } else if (currentStep == 1 && ContactState.formKey.currentState.validate()) { currentStep = currentStep + 1; } } else { currentStep = 0; } }); }, onStepCancel: () { setState(() { if (currentStep > 0) { currentStep = currentStep - 1; } else { currentStep = 0; } }); }, ), ), ); } }
personal.dart
import 'package:flutter/material.dart'; class Personal extends StatefulWidget { @override State<StatefulWidget> createState() { // TODO: implement createState return PersonalState(); } } class PersonalState extends State<Personal> { static final formKey = GlobalKey<FormState>(); static TextEditingController controllerFirstName = new TextEditingController(); static TextEditingController controllerLastName = new TextEditingController(); static TextEditingController controllerDateOfBirth = new TextEditingController(); static TextEditingController controllerGender = new TextEditingController(); @override Widget build(BuildContext context) { // TODO: implement build return Container( child: Form( key: formKey, autovalidate: false, child: Column( children: <Widget>[ TextFormField( maxLines: 1, controller: controllerFirstName, decoration: InputDecoration( prefixIcon: const Icon( Icons.person, color: Colors.grey, ), hintText: 'First Name', border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), ), ), validator: (value) { if (value.trim().isEmpty) { return "First Name is Required"; } }, ), SizedBox(height: 20), TextFormField( maxLines: 1, decoration: InputDecoration( prefixIcon: const Icon( Icons.person, color: Colors.grey, ), hintText: 'Last Name', border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), ), ), validator: (value) { if (value.trim().isEmpty) { return "Last Name is Required"; } }, controller: controllerLastName), SizedBox(height: 20), TextFormField( maxLines: 1, decoration: InputDecoration( prefixIcon: const Icon( Icons.calendar_today, color: Colors.grey, ), hintText: 'Date of Birth', border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), ), ), controller: controllerDateOfBirth), SizedBox(height: 20), TextFormField( maxLines: 1, decoration: InputDecoration( prefixIcon: const Icon( Icons.person, color: Colors.grey, ), hintText: 'Gender', border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), ), ), controller: controllerGender), ], ), )); } }
contact.dart
import 'package:flutter/material.dart'; class Contact extends StatefulWidget { @override State<StatefulWidget> createState() { // TODO: implement createState return ContactState(); } } class ContactState extends State<Contact> { static final formKey = GlobalKey<FormState>(); static TextEditingController controllerEmail = new TextEditingController(); static TextEditingController controllerAddress = new TextEditingController(); static TextEditingController controllerMobileNo = new TextEditingController(); @override Widget build(BuildContext context) { // TODO: implement build return Container( child: Form( key: formKey, autovalidate: false, child: Column( children: <Widget>[ TextFormField( maxLines: 1, decoration: InputDecoration( prefixIcon: const Icon( Icons.email, color: Colors.grey, ), hintText: 'Email', border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), ), ), validator: (value) { if (value.trim().isEmpty) { return "Email is Required"; } }, controller: controllerEmail, ), SizedBox(height: 20), TextFormField( minLines: 5, maxLines: 7, decoration: InputDecoration( prefixIcon: const Icon( Icons.home, color: Colors.grey, ), hintText: 'Address', border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), ), ), controller: controllerAddress, ), SizedBox(height: 20), TextFormField( maxLines: 1, decoration: InputDecoration( prefixIcon: const Icon( Icons.phone, color: Colors.grey, ), hintText: 'Mobile No', border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), ), ), validator: (value) { if (value.trim().isEmpty) { return "Mobile No is Required"; } }, controller: controllerMobileNo, ), ], ), ) ); } }
upload.dart
import 'dart:collection'; import 'package:flutter/material.dart'; class Upload extends StatefulWidget { var mapInfo = HashMap<String,String>(); Upload(this.mapInfo); @override State<StatefulWidget> createState() { // TODO: implement createState return UploadState(); } } class UploadState extends State<Upload> { @override Widget build(BuildContext context) { var name = widget.mapInfo["first_name"] + " " + widget.mapInfo["last_name"]; var dob = widget.mapInfo["date_of_birth"]; var gender = widget.mapInfo["gender"]; var email = widget.mapInfo["email"]; var address = widget.mapInfo["address"]; var mobile = widget.mapInfo["mobile_no"]; // TODO: implement build return Container( child: Column( children: <Widget>[ Row( children: <Widget>[ Text("Name: ", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),), Text(name, style: TextStyle(fontSize: 16)), ], ), SizedBox(height: 20), Row( children: <Widget>[ Text("Date of Birth: ", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),), Text(dob, style: TextStyle(fontSize: 16)), ], ), SizedBox(height: 20), Row( children: <Widget>[ Text("Gender: ", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),), Text(gender, style: TextStyle(fontSize: 16)), ], ), SizedBox(height: 20), Row( children: <Widget>[ Text("Email: ", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),), Text(email, style: TextStyle(fontSize: 16)), ], ), SizedBox(height: 20), Row( children: <Widget>[ Text("Address: ", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),), Text(address, style: TextStyle(fontSize: 16)), ], ), SizedBox(height: 20), Row( children: <Widget>[ Text("Mobile No: ", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),), Text(mobile, style: TextStyle(fontSize: 16)), ], ), ], ), ); } }






Pingback: Confetti Animation Flutter Example - CodingWithDhrumil