import 'package:flutter/material.dart'; import '../../helpers/theme.dart'; class StepperWidget extends StatefulWidget { final int currentStep; final List labels; final double eachStepWidth; final double height; final ValueChanged? onChange; const StepperWidget( {Key? key, this.currentStep = 0, required this.labels, this.eachStepWidth = 100, this.height = 80, this.onChange}) : super(key: key); @override State createState() => _StepperWidgetState(); } class _StepperWidgetState extends State { @override Widget build(BuildContext context) { var body = _body(); return Center( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: body)); } Widget _body() { return SizedBox( width: widget.eachStepWidth * widget.labels.length, height: widget.height, child: Stack( children: [ Positioned( bottom: 13, left: widget.eachStepWidth / 2, child: Container( margin: const EdgeInsets.symmetric(horizontal: 0.0), height: 1.0, width: widget.eachStepWidth * (widget.labels.length - 1), color: Colors.grey.shade400, ), ), Row( children: widget.labels.asMap().entries.map((e) { return StepWidget( label: e.value, step: e.key, stepWidth: widget.eachStepWidth, currentStep: widget.currentStep, onTap: () => _onTap(e.key), end: e.key == widget.labels.length - 1, ); }).toList()), ], ), ); } _onTap(int index) { if (widget.onChange != null) { widget.onChange!(index); } } } class StepWidget extends StatelessWidget { final String label; final int step; final double stepWidth; final int currentStep; final GestureTapCallback? onTap; final bool end; const StepWidget( {Key? key, required this.label, required this.step, this.stepWidth = 100, required this.currentStep, this.onTap, this.end = false}) : super(key: key); @override Widget build(BuildContext context) { bool active = step == currentStep; bool past = step < currentStep; return InkWell( onTap: onTap, child: SizedBox( width: stepWidth, child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ Text(label, textAlign: TextAlign.center, style: TextStyle( color: active ? primaryColor : Colors.grey, fontFamily: "Roboto")), const SizedBox(height: 5), CircleAvatar( backgroundColor: end && active ? primaryColor : active || past ? primaryColor : Colors.grey, radius: 13, child: end ? const Icon(Icons.check, color: Colors.white, size: 20) : Text( (step + 1).toString(), style: const TextStyle(color: Colors.white), ), ) ], ), ), ); } }