You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
diplomatic-quarter/lib/widgets/carousel_indicator/carousel_indicator.dart

198 lines
5.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class CarouselIndicator extends StatefulWidget {
/// width of the indicator
final double width;
/// height of the indicator
final double height;
/// space between indicators.
final double space;
/// count of indicator
final int count;
/// active color
final Color activeColor;
/// normal color
final Color color;
/// use this to give some radius to the corner indicator
final double cornerRadius;
/// duration for slide animation
final int animationDuration;
final int index;
final Function(int index) onClick;
CarouselIndicator({
Key key,
this.width: 20.0,
this.height: 6,
this.space: 5.0,
this.count,
this.cornerRadius: 6,
this.animationDuration: 300,
this.color: Colors.white30,
this.index,
this.activeColor: Colors.white,
this.onClick
}) : assert(count != null && count != 0),
assert(index != null && index >= 0),
super(key: key);
@override
State<StatefulWidget> createState() {
return new _CarouselIndicatorState();
}
}
class _CarouselIndicatorState extends State<CarouselIndicator>
with TickerProviderStateMixin {
/// [Tween] object of type double
Tween<double> _tween;
/// [AnimationController] object
AnimationController _animationController;
/// [Aniamtion] object
Animation _animation;
/// [Paint] object to paint our indicator
Paint _paint = new Paint();
/// Method to initilize [BasePainter] to paint indicators.
BasePainter _createPainer() {
return SlidePainter(widget, _animation.value, _paint);
}
@override
Widget build(BuildContext context) {
Widget child = new SizedBox(
width: widget.count * widget.width + (widget.count - 1) * widget.space,
height: widget.height,
child: CustomPaint(
painter: _createPainer(),
),
);
return InkWell(
child: child,
onTap: (){
if(widget.onClick != null)
widget.onClick(0);
},
);
}
@override
void initState() {
/// for initial index=0 we do not want to change any value so setting [_tween] to (0.0,0.0),
createAnimation(0.0, 0.0);
super.initState();
}
@override
void didUpdateWidget(CarouselIndicator oldWidget) {
if (widget.index != oldWidget.index) {
if (widget.index != 0) {
_animationController.reset();
/// for each new index we want to change value so setting [_tween] to (oldWidget.index,widget.index) so animation tween from old position to new position rather not start from 0.0 again and again.
createAnimation(oldWidget.index.toDouble(), widget.index.toDouble());
_animationController.forward();
} else {
_animationController.reset();
createAnimation(oldWidget.index.toDouble(), 0.0);
_animationController.forward();
}
}
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
void createAnimation(double begin, double end) {
_tween = Tween(begin: begin, end: end);
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: widget.animationDuration));
_animation = _tween.animate(_animationController)
..addListener(() {
setState(() {});
});
}
}
/// Base Painter class to draw indicator
abstract class BasePainter extends CustomPainter {
final CarouselIndicator widget;
final double page;
final Paint _paint;
BasePainter(this.widget, this.page, this._paint);
/// This method will get body to class extending [BasePainter] and this method will draw the sliding indicator which slide over changing index.
void draw(Canvas canvas, double space, double width, double height,
double radius, double cornerRadius);
@override
void paint(Canvas canvas, Size size) {
_paint.color = widget.color;
double space = widget.space;
double width = widget.width;
double height = widget.height;
double distance = width + space;
double radius = width / 2;
for (int i = 0, c = widget.count; i < c; ++i) {
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromCenter(
center: Offset((i * distance) + radius, radius),
width: width,
height: height),
Radius.circular(widget.cornerRadius)),
_paint);
}
_paint.color = widget.activeColor;
draw(canvas, space, width, height, radius, widget.cornerRadius);
}
@override
bool shouldRepaint(BasePainter oldDelegate) {
return oldDelegate.page != page;
}
}
/// This class we draw the indicator which slides.
class SlidePainter extends BasePainter {
SlidePainter(CarouselIndicator widget, double page, Paint paint)
: super(widget, page, paint);
@override
void draw(Canvas canvas, double space, double width, double height,
double radius, double cornerRadius) {
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromCenter(
center: Offset(radius + (page * (width + space)), radius),
width: width,
height: height),
Radius.circular(cornerRadius)),
_paint);
}
}