Making a Custom Number Stepper in Flutter
Flutter has an awesome widget for making Stepper. Using which we can make both horizontal and vertical steppers. You can check from their documentation. But it doesn’t provide much of a customization. So, why not making our own like the gif? Let’s get started.
At first we will make a new class StatelessWidget
named NumberStepper
, We will define some properties like width
, curStep
, totalSteps
, stepCompleteColor
, currentStepColor
, inactiveColor
and lineWidth
inside the class.
class NumberStepper extends StatelessWidget {
final double width;
final totalSteps;
final int curStep;
final Color stepCompleteColor;
final Color currentStepColor;
final Color inactiveColor;
final double lineWidth;
NumberStepper({
Key key,
@required this.width,
@required this.curStep,
@required this.stepCompleteColor,
@required this.totalSteps,
@required this.inactiveColor,
@required this.currentStepColor,
@required this.lineWidth,
}) : assert(curStep > 0 == true && curStep <= totalSteps + 1),
super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(
top: 20.0,
left: 24.0,
right: 24.0,
),
width: this.width,
child: Row(
children: _steps(),
),
);
}
}
Inside build widget we defined another method _steps()
that return a List<Widget>
where we concatenate the Step Circles and Lines connecting them.
List<Widget> _steps() {
var list = <Widget>[];
for (int i = 0; i < totalSteps; i++) {
//colors according to state
var circleColor = getCircleColor(i);
var borderColor = getBorderColor(i);
var lineColor = getLineColor(i);
// step circles
list.add(
Container(
width: 28.0,
height: 28.0,
child: getInnerElementOfStepper(i),
decoration: new BoxDecoration(
color: circleColor,
borderRadius: new BorderRadius.all(new Radius.circular(25.0)),
border: new Border.all(
color: borderColor,
width: 1.0,
),
),
),
);
//line between step circles
if (i != totalSteps - 1) {
list.add(
Expanded(
child: Container(
height: lineWidth,
color: lineColor,
),
),
);
}
}
return list;
}
Then, the getInnerElementOfStepper()
method returns inner element according to current step of stepper. If the current step is greater than step index it shows checked icon. If the current step is equal to the index it shows the number of that step. And if the current step is less than the step index it shows blank circle.
Widget getInnerElementOfStepper(index) {
if (index + 1 < curStep) {
return Icon(
Icons.check,
color: Colors.white,
size: 16.0,
);
} else if (index + 1 == curStep) {
return Center(
child: Text(
'$curStep',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.bold,
fontFamily: 'Roboto',
),
),
);
} else
return Container();
}
We also define colors for different states of stepper.
getCircleColor(i) {
var color;
if (i + 1 < curStep) {
color = stepCompleteColor;
} else if (i + 1 == curStep)
color = currentStepColor;
else
color = Colors.white;
return color;
}
getBorderColor(i) {
var color;
if (i + 1 < curStep) {
color = stepCompleteColor;
} else if (i + 1 == curStep)
color = currentStepColor;
else
color = inactiveColor;
return color;
}
getLineColor(i) {
var color =
curStep > i + 1 ? Colors.blue.withOpacity(0.4) : Colors.grey[200];
return color;
}
So, this is all for our NumberStepper Class
, now all we need to do is use it from anywhere in your application.
NumberStepper(
totalSteps: stepLength,
width: MediaQuery.of(context).size.width,
curStep: currentStep,
stepCompleteColor: Colors.blue,
currentStepColor: Color(0xffdbecff),
inactiveColor: Color(0xffbababa),
lineWidth: 3.5,
)
So, here comes our final output.
to handle the currentStep
value with those Back button and Next button, you can use this code.
int currentStep = 1;
int stepLength = 5;
bool complete;
next() {
if (currentStep <= stepLength) {
goTo(currentStep + 1);
}
}
back() {
if (currentStep > 1) {
goTo(currentStep - 1);
}
}
goTo(int step) {
setState(() => currentStep = step);
if (currentStep > stepLength) {
setState(() => complete = true);
}
}
This is how we can make a custom Number stepper. You can do a lot of customization if you want.
This is my first article on medium, Hope you enjoyed it. You can find the full source code here.