Skip to content

Instantly share code, notes, and snippets.

@guptahitesh121
Created March 4, 2020 14:15
Show Gist options
  • Save guptahitesh121/0e0b67cbf14c71f0f424b2ed7a9848b6 to your computer and use it in GitHub Desktop.
Save guptahitesh121/0e0b67cbf14c71f0f424b2ed7a9848b6 to your computer and use it in GitHub Desktop.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Swipe Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: SafeArea(
child: Container(
color: Colors.white,
child: MStepperDemo(),
),
),
),
);
}
}
class MStepperDemo extends StatefulWidget {
@override
MStepperDemoState createState() => MStepperDemoState();
}
class MStepperDemoState extends State<MStepperDemo> {
int _activeIndex = 0;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: MStepper(
steps: <Widget>[
_buildStep('1', Colors.yellow),
_buildStep('2', Colors.green),
_buildStep('3', Colors.orange),
_buildStep('4', Colors.blue),
_buildStep('5', Colors.red),
],
activeIndex: _activeIndex,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('Previous'),
onPressed: () {
if (_activeIndex > 0)
setState(() {
_activeIndex--;
});
},
),
SizedBox(width: 16),
RaisedButton(
child: Text('Next'),
onPressed: () {
if (_activeIndex < 4)
setState(() {
_activeIndex++;
});
},
),
],
)
],
);
}
Widget _buildStep(String text, Color color) {
return Container(
constraints: BoxConstraints.expand(),
alignment: Alignment.center,
color: color,
child: Text(
text,
style: TextStyle(fontSize: 400),
),
);
}
}
class MStepper extends StatefulWidget {
final List<Widget> steps;
final int activeIndex;
final BoxConstraints constraints;
final Alignment alignment;
final Duration speed;
MStepper({
this.steps,
this.activeIndex,
this.constraints = const BoxConstraints.expand(),
this.alignment = Alignment.center,
this.speed = const Duration(milliseconds: 220),
}) : assert(steps != null && steps.isNotEmpty);
@override
StepperState createState() => StepperState();
int get safeActiveIndex {
if (activeIndex == null || activeIndex < 0) return 0;
if (activeIndex >= steps.length) return steps.length - 1;
return activeIndex;
}
}
class StepperState extends State<MStepper> {
static const double StepWidgetSize = 55;
static const double StepWidgetBorderSize = 5;
static const double SeparatorWidth = 15;
static const Color ActiveColor = const Color(0xFF80AB37);
static const Color InactiveColor = const Color(0xFFBCBCBC);
static const Color SecondaryColor = const Color(0xFFE1E1DF);
int _activeIndex;
int _oldActiveIndex;
@override
void initState() {
_activeIndex = widget.safeActiveIndex;
_oldActiveIndex = widget.safeActiveIndex;
super.initState();
}
@override
void didUpdateWidget(MStepper oldWidget) {
_activeIndex = widget.safeActiveIndex;
_oldActiveIndex = oldWidget.safeActiveIndex;
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 20, bottom: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _buildStepCounter().separate(
_buildSeparator(),
),
),
),
Expanded(
child: AnimatedSwitcher(
duration: widget.speed,
transitionBuilder: (Widget child, Animation<double> animation) {
final dxIn = _activeIndex > _oldActiveIndex ? 1.0 : -1.0;
final dxOut = _activeIndex > _oldActiveIndex ? -1.0 : 1.0;
final inAnimation = Tween<Offset>(begin: Offset(dxIn, 0), end: Offset(0, 0)).animate(animation);
final outAnimation = Tween<Offset>(begin: Offset(dxOut, 0), end: Offset(0, 0)).animate(animation);
if (child.key == ValueKey<int>(_activeIndex)) {
return SlideTransition(
position: inAnimation,
child: child,
);
} else {
return SlideTransition(
position: outAnimation,
child: child,
);
}
},
child: Container(
key: ValueKey<int>(_activeIndex),
constraints: widget.constraints,
alignment: widget.alignment,
child: widget.steps[_activeIndex],
),
),
),
],
);
}
List<Widget> _buildStepCounter() {
List<Widget> steps = [];
for (var i = 0; i < widget.steps.length; i++) {
steps.add(_buildCircle(i));
}
return steps;
}
Widget _buildCircle(int index) {
return AnimatedContainer(
duration: widget.speed,
curve: Curves.easeIn,
width: StepWidgetSize,
height: StepWidgetSize,
alignment: Alignment.center,
decoration: BoxDecoration(
color: index <= _activeIndex ? ActiveColor : InactiveColor,
shape: BoxShape.circle,
border: Border.all(
width: StepWidgetBorderSize,
color: SecondaryColor,
),
),
child: _buildCircleChild(index),
);
}
Widget _buildCircleChild(int index) {
return Text(
(index + 1).toString(),
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
);
}
Widget _buildSeparator() {
return Container(
width: SeparatorWidth,
height: StepWidgetBorderSize,
color: SecondaryColor,
);
}
}
extension MyIterable<E> on Iterable<E> {
List<E> separate(E separator) {
assert(separator != null);
Iterator<E> iterator = this.iterator;
List<E> buffer = <E>[];
if (!iterator.moveNext()) return buffer;
buffer.add(iterator.current);
while (iterator.moveNext()) {
buffer.add(separator);
buffer.add(iterator.current);
}
return buffer;
}
}
@guptahitesh121
Copy link
Author

Stepper

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment