flutter flutter_swiper自定义指示器

转载请注明出处:王亟亟的大牛之路

最近在做公司项目的一些模块迁移的尝试,然后在改Banner的时候发现官方并没有提供封装彻底的ViewPager控件,然后第三方里我选了 https://github.com/best-flutter/flutter_swiper
理由有以下几点

  1. 有人维护,且仍在继续开发
  2. 文档解释比较清晰
  3. 使用比较简便
  4. 满足了业务效果

官方的演示效果

设计稿长这样
flutter flutter_swiper自定义指示器_第1张图片

可以发现他的指示器是圆的,然而我们的是方的,所以带着疑问我看了下他的文档

flutter flutter_swiper自定义指示器_第2张图片
官方对自定义指示器是有支持的,先看一下他支持传入什么控件

class SwiperCustomPagination extends SwiperPlugin {
  final SwiperPaginationBuilder builder;

  SwiperCustomPagination({@required this.builder}) : assert(builder != null);

  @override
  Widget build(BuildContext context, SwiperPluginConfig config) {
    return builder(context, config);
  }
}

可以传任意控件,那我们假装丢个text试试看

flutter flutter_swiper自定义指示器_第3张图片

试试发现是有效的,带着疑问去看一下他的指示器实现类PageIndicator

开源团队把指示器这块单独做了一个依赖lib在https://github.com/best-flutter/flutter_page_indicator

  PageIndicator(
      {Key key,
      this.size: 20.0,
      this.space: 5.0,
      this.count,
      this.activeSize: 20.0,
      this.controller,
      this.color: Colors.white30,
      this.layout: PageIndicatorLayout.SLIDE,
      this.activeColor: Colors.white,
      this.scale: 0.6,
      this.dropHeight: 20.0})
      : assert(count != null),
        assert(controller != null),
        super(key: key);

  @override
  State createState() {
    return new _PageIndicatorState();
  }
}

构造函数一大堆但是我们真正在乎的其实只有this.layout: PageIndicatorLayout.SLIDE,

这是具体那个View的实现,当然官方提供了很多种类型,大家可以自己去看我这边选择了PageIndicatorLayout.NONE进行改造


添加枚举的类型

对外暴露的枚举类型决定了调用哪个子类的实现,为了不破坏原有的类型,这边就添加一个新的枚举值

enum PageIndicatorLayout {
  NONE,
  SLIDE,
  WARM,
  COLOR,
  SCALE,
  DROP,
  NIO,//你自己随便定吧
}

添加枚举值对应的实现

这便是拿NonePainter实现进行修改,区别就是把画圆的动画过程全部变成了画线

class NioPainter extends NioBasePainter {
  NioPainter(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 = styles.ComponentStyle.APP_MAIN_COLOR;
    _paint.strokeWidth = 3;
    //只修改这里就可以满足效果
    canvas.drawLine(new Offset(secondOffset - 8, radius),
        new Offset(secondOffset + 8, radius), _paint);
  }
}

修改指示器背景Widget实现

在继承和复制之间我选择了整个文件copy然后在内部改造,继承还要看原来的代码里是否暴露了足够的成员方法,个人觉得不是太有必要,索性直接copy,反正也就一个文件。

背景点的实现就在BasePainter里,他是一个抽象类,里面代码里几十行,但是我们其实只需要把默认的背景灰点换成直线就行,找到paint方法进行修改。

abstract class NioBasePainter extends BasePainter {
   ...
  @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;
      }
      //8只是一种横线多宽自己算吧,反正就是一个不同x坐标同y坐标的一条直线
     canvas.drawLine(new Offset(i * (size + space) + radius - 8, 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);
  }
}

...省略其他代码
class _PageIndicatorState extends State {
BasePainter _createPainer() {
    switch (widget.layout) {
      case PageIndicatorLayout.NIO:
      //添加自己新加的枚举值多对应的动态指示器实现
        return new NioPainter(
            widget, widget.controller.page ?? 0.0, index, _paint);
      ...省略其他代码
      default:
        throw new Exception("Not a valid layout");
    }
  }
}

实现的效果
flutter flutter_swiper自定义指示器_第4张图片

源码地址:https://github.com/ddwhan0123/flutter_tutorial/blob/master/lib/component/widget/page_indicator.dart

基本满足了设计稿的要求,当然实现的有点粗糙还需要润色下,这篇还是一次实现过程的经历,没有特别的内容分析,谢谢!

有疑问欢迎加我沟通(必须注明来源来意,谢谢)
flutter flutter_swiper自定义指示器_第5张图片

你可能感兴趣的:(Flutter,混合开发,viewpager,flutter,swiper,PageIndicator)