手撸一个flutter轮播图

在移动端轮播图是比较常见的一种UI布局,在web端实现起来比较简单,了解flutter一段时间后,想用flutter撸一个轮播图出来,苦于无从下手(对flutter的内置组件还不是很熟悉),最后参考了其他的大佬文章,才有了思路,这里做一个小小的技术积累。

效果图

QQ20191111-204526-HD.gif

1.了解需求

  1. 轮播图具有自动翻页
  2. 可以手势拖动翻页,点击事件
  3. 有个指示器
  4. 轮播图的一些基础属性,高度等

2.通用Banner组件设计

一般如果是项目通用的banner的话,需要设计一些比较通用的配置属性项,再其他页面也能够很轻松的使用,比如轮播图的高度,点击事件的回调函数,切换的动画效果,切换的时间间隔等。

2.1 定义一个CustomBanner类
// 构造函数
CustomBanner(
  this._images, 
  {
    this.height = 200,
    this.onTap,
    this.curve = Curves.linear,
    this.timeSeconds = 3,
  }
) : asset(_images != null);
  • _images: 给组件传一个图片的链接列表
  • height: 组件的高度,默认值是200
  • onTap:点击的回调函数,回调传了一个ValueChange,当前的点击的下标
  • curve: 切换的动画
  • timeSeconds: 切换的时间间隔

2.2 使用flutter内置Widget PageView

有轮播切换效果的Widget,flutter已经内置有了PageView,这个Widget是可以左右切换页面的效果,能够满足我们的需求。

  • 定义一个PageView Widget
Widget _buildPageView() {
  return new Container(
    height: widget.height, // 组件高度
    child: PageView.builder( // 使用builder是可以创建一个无限滚动的页面
      onPageChange: (index) {
        setState(() {
            _curIndex = index;
            if (index == 0) {
               _curIndex = length;
            }
        })
      },
      itemBuilder: (BuildContext context, int index) {
        return Image.network(
           widget._images[index % length],
           fit: BoxFit.cover,
         ),
      });
    ),
  );
}
  • 左边无限循环切换:
    在onPageChange事件中,当index == 0的时候,把 _curIndex = length;在itemBuilder中返回的每一项是当前的index对图片数组取余,再往左滑动的时候,当滑到index为0,那么下一张应该是length-1,length-1的下一张是0,所以需要把_curIndex = length,同时需要_pageController.jumpToPage(_curIndex);页面切换到最后一张的下一张,然后就能往左无限的滑动了。

    image.png

  • 添加轮播指示器_buildIndicator
    在最外层用Stack Widget包裹_buildPageView_buildIndicator;新创建的_buildIndicator定位到底部,具体代码如下:

Widget _buildIndicator() {
  return Positioned(
    bottom: 10,
    child: Row(
      children: widget._images.map((s) {
        padding: const EdgeInsets.symmetric(horizontal: 3.0), // 水平padding
        child: ClipOval( // 原型can'j
          child: Container(
             width: 8,
             height: 8,
             color: s == widget._images[_curIndex % length] ? Colors.white : Colors.grey,
          ), // 当前元素等于图片中显示的元素的时候,是白色圆点,否则是灰色
        ),
      }).toList()
    )
  )
}

PageView onPageChanged后,setState _curIndex 的值,这样指示器就能跟着图片一起变动。

2.3 让图片自动切换

上面的一些操作之后,基本上功能已经实现,手动可以无限切换轮播,那么自动轮播的话,这里需要用到flutter的Timer

  • 初始化数据定义一个Timer
    利用Timer.periodic()来创建一个循环定时任务,这个相当于web的setInterval, 回调函数是达到间隔后执行的函数
_initTimer() {
    if (_timer == null) {
      _timer = Timer.periodic(Duration(seconds: widget.timeSeconds), (t) {
        _curIndex++;
        _pageController.animateToPage( // 动画切换
          _curIndex,
          duration: Duration(milliseconds: 300),
          curve: Curves.linear,
        );
      });
    }
  }

到这里基本上一个轮播组件就基本上完成了,点击事件的添加,在图片外层加一个GestureDetector手势,添加onTap事件;本来想着在图片滑动时去清掉定时任务,滑动结束后再重新初始化定时任务的,但是好像PageView和手势有冲突,只执行了onPanDownonPanUpdateonPanEnd不会触发。所以解决方案是在onPanDown时Timer.cancel清除定时,然后再初始化定时任务。

  • 用法
body: Column(
        children: [
          CustomBanner(_images),
          new Container(
            padding: const EdgeInsets.only(top: 10.0),
            child: CustomBanner(_images1, timeSeconds: 1),
          ),
        ],
      )
QQ20191112-163710-HD.gif

总结

通过做一个flutter的轮播图,对dart语法又有了更加深入的了解,对flutter自定义组件的封装,布局,常用的Widget也有了一定的了解。

你可能感兴趣的:(手撸一个flutter轮播图)