flutter_swiper指示器样式默认只有SwiperPagination.dots(圆点)和SwiperPagination.fraction(数字)两种显示效果,文档提到可以自定义自己的指示器,但是没有给出具体的文档例子。文档有提到指示器是单独放在flutter_page_indicator实现,看了下源代码发现绘制是使用canvas进行绘制的,所以要想实现其他样式效果,貌似只能修改源代码实现。当然,不能直接编辑插件源代码,所以这里选择了copy整个文件放到自己的组件代码中,在这个文件中添加新的样式实现:
主要修改点:
新增LinePainter类和LineBasePainter抽象类
LinePainter
class LinePainter extends LineBasePainter {
LinePainter(PageIndicator widget, double page, int index, Paint paint)
: super(widget, page, index, paint);
@override
void draw(Canvas canvas, double space, double size, double radius) {
double secondOffset = index == widget.count - 1
? radius
: radius + ((index + 1) * (size + space));
_paint.color = AppColors.app_main;
_paint.strokeWidth = 3;
canvas.drawLine(new Offset(secondOffset - 8, radius),
new Offset(secondOffset + 8, radius), _paint);
}
}
LineBasePainter
abstract class LineBasePainter extends BasePainter {
final PageIndicator widget;
final double page;
final int index;
final Paint _paint;
double lerp(double begin, double end, double progress) {
return begin + (end - begin) * progress;
}
LineBasePainter(this.widget, this.page, this.index, this._paint)
: super(widget, page, index, _paint);
void draw(Canvas canvas, double space, double size, double radius);
bool _shouldSkip(int index) {
return false;
}
//double secondOffset = index == widget.count-1 ? radius : radius + ((index + 1) * (size + space));
@override
void paint(Canvas canvas, Size size) {
_paint.color = widget.color;
double space = widget.space;
double size = widget.size;
double radius = size / 2;
for (int i = 0, c = widget.count; i < c; ++i) {
if (_shouldSkip(i)) {
continue;
}
// 这里的4指不是当前index的宽度,8是当前index的宽度,效果请看下面效果图
canvas.drawLine(new Offset(i * (size + space) + radius - 4, radius),
new Offset(i * (size + space) + radius + 8, radius), _paint);
}
double page = this.page;
if (page < index) {
page = 0.0;
}
_paint.color = widget.activeColor;
draw(canvas, space, size, radius);
}
@override
bool shouldRepaint(BasePainter oldDelegate) {
return oldDelegate.page != page;
}
}
enum PageIndicatorLayout {
NONE,
SLIDE,
WARM,
COLOR,
SCALE,
DROP,
LINE, // 添加的横线类型
}
在_PageIndicatorState的_createPainer方法中新增:
BasePainter _createPainer() {
switch (widget.layout) {
case PageIndicatorLayout.LINE:
return new LinePainter(
widget, widget.controller.page ?? 0.0, index, _paint);
case PageIndicatorLayout.NONE:
....
}
}
最后在使用页面中导入这个文件后,示例写法:
Swiper(
itemBuilder: (BuildContext context,int index){
return _plateCard();
},
itemCount: 3,
pagination: SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) {
return Container(
alignment: Alignment.bottomCenter,
height: 90,
child: PageIndicator(
layout: PageIndicatorLayout.LINE,
size: 10.0,
space: 10.0,
count: 3,
controller: config.pageController,
color: Colors.black12,
),
);
}),
)
实现效果:
自定义指示器样式最后
如果你有更好的方式实现,欢迎留言,谢谢
网友评论