Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import 'package:flutter/material.dart';
class StepperWidget extends StatelessWidget {
const StepperWidget({
Key key,
@required this.tabController,
@required this.headings,
@required this.textStyle,
this.height = 48.0,
this.spacing = 2.0,
this.child,
}) : super(key: key);
final TabController tabController;
final List<String> headings;
final TextStyle textStyle;
final double spacing;
final double height;
final Widget child;
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: _StepperPainter(
spacing: spacing,
controller: tabController,
headings: headings,
textStyle: textStyle,
),
size: Size(double.infinity, height),
child: child,
);
}
}
class _StepperPainter extends CustomPainter {
_StepperPainter({
this.controller,
this.headings,
this.spacing,
this.textStyle,
}) : super(repaint: controller.animation) {
_textPainter = TextPainter(
textDirection: TextDirection.ltr,
maxLines: 2,
ellipsis: '…',
);
}
final TabController controller;
final List<String> headings;
final double spacing;
final TextStyle textStyle;
TextPainter _textPainter;
@override
void paint(Canvas canvas, Size size) {
double animation = controller.animation.value;
int count = headings.length;
double height = size.height;
double depth = height * 0.33;
double width = (size.width - ((count - 1) * spacing)) / count;
Paint paint = Paint()..strokeCap = StrokeCap.butt;
for (int p = 0; p < 2; p++) {
paint.color = p == 0 ? Colors.grey[300] : Colors.greenAccent;
int max = (p == 0 ? count - 1 : animation.ceil());
for (int i = max; i >= 0; i--) {
Path path = Path();
double fraction;
double secondPage = 1.0 + animation;
if (p == 1 && secondPage >= i && secondPage < i + 1) {
fraction = (secondPage % 1.0);
} else {
fraction = 1.0;
}
path.moveTo(width * (i + fraction) + (i * spacing), 0.0);
path.relativeLineTo(depth, height / 2);
path.relativeLineTo(-depth, height / 2);
path.relativeLineTo(-width * fraction, 0.0);
if (i > 0) {
path.relativeLineTo(depth, -height / 2);
path.relativeLineTo(-depth, -height / 2);
} else {
path.relativeLineTo(0.0, -height);
}
canvas.drawPath(path, paint);
_textPainter.text = TextSpan(
text: headings[i],
style: textStyle.copyWith(
color: i <= int.parse(animation.toStringAsFixed(0))
? Colors.white
: Colors.black,
),
);
_textPainter.layout(maxWidth: width - depth - (depth * 0.5));
_textPainter.paint(
canvas,
Offset(
(width + spacing) * i + (depth * 0.5) + (i > 0 ? depth : 0.0),
(height - _textPainter.height) * 0.5,
),
);
}
}
}
@override
bool shouldRepaint(_StepperPainter oldDelegate) => true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment