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, ), ); }), )
實現效果:

自定義指示器樣式
最后
如果你有更好的方式實現,歡迎留言,謝謝
作者:打靜爵
鏈接:https://www.jianshu.com/p/d4b406bca164
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。