Flutter

修改flutter_swiper指示器样式

2019-08-04  本文已影响0人  打静爵

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,
                  ),
                );
              }),
            )

实现效果:

自定义指示器样式

最后

如果你有更好的方式实现,欢迎留言,谢谢

上一篇下一篇

猜你喜欢

热点阅读