手?jǐn)]一個flutter輪播圖

在移動端輪播圖是比較常見的一種UI布局,在web端實現(xiàn)起來比較簡單,了解flutter一段時間后,想用flutter擼一個輪播圖出來,苦于無從下手(對flutter的內(nèi)置組件還不是很熟悉),最后參考了其他的大佬文章,才有了思路,這里做一個小小的技術(shù)積累。

效果圖

QQ20191111-204526-HD.gif

1.了解需求

  1. 輪播圖具有自動翻頁
  2. 可以手勢拖動翻頁,點擊事件
  3. 有個指示器
  4. 輪播圖的一些基礎(chǔ)屬性,高度等

2.通用Banner組件設(shè)計

一般如果是項目通用的banner的話,需要設(shè)計一些比較通用的配置屬性項,再其他頁面也能夠很輕松的使用,比如輪播圖的高度,點擊事件的回調(diào)函數(shù),切換的動畫效果,切換的時間間隔等。

2.1 定義一個CustomBanner類
// 構(gòu)造函數(shù)
CustomBanner(
  this._images, 
  {
    this.height = 200,
    this.onTap,
    this.curve = Curves.linear,
    this.timeSeconds = 3,
  }
) : asset(_images != null);
  • _images: 給組件傳一個圖片的鏈接列表
  • height: 組件的高度,默認(rèn)值是200
  • onTap:點擊的回調(diào)函數(shù),回調(diào)傳了一個ValueChange<int>,當(dāng)前的點擊的下標(biāo)
  • curve: 切換的動畫
  • timeSeconds: 切換的時間間隔

2.2 使用flutter內(nèi)置Widget PageView

有輪播切換效果的Widget,flutter已經(jīng)內(nèi)置有了PageView,這個Widget是可以左右切換頁面的效果,能夠滿足我們的需求。

  • 定義一個PageView Widget
Widget _buildPageView() {
  return new Container(
    height: widget.height, // 組件高度
    child: PageView.builder( // 使用builder是可以創(chuàng)建一個無限滾動的頁面
      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,
         ),
      });
    ),
  );
}
  • 左邊無限循環(huán)切換:
    在onPageChange事件中,當(dāng)index == 0的時候,把 _curIndex = length;在itemBuilder中返回的每一項是當(dāng)前的index對圖片數(shù)組取余,再往左滑動的時候,當(dāng)滑到index為0,那么下一張應(yīng)該是length-1,length-1的下一張是0,所以需要把_curIndex = length,同時需要_pageController.jumpToPage(_curIndex);頁面切換到最后一張的下一張,然后就能往左無限的滑動了。

    image.png

  • 添加輪播指示器_buildIndicator
    在最外層用Stack Widget包裹_buildPageView_buildIndicator;新創(chuàng)建的_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,
          ), // 當(dāng)前元素等于圖片中顯示的元素的時候,是白色圓點,否則是灰色
        ),
      }).toList()
    )
  )
}

PageView onPageChanged后,setState _curIndex 的值,這樣指示器就能跟著圖片一起變動。

2.3 讓圖片自動切換

上面的一些操作之后,基本上功能已經(jīng)實現(xiàn),手動可以無限切換輪播,那么自動輪播的話,這里需要用到flutter的Timer

  • 初始化數(shù)據(jù)定義一個Timer
    利用Timer.periodic()來創(chuàng)建一個循環(huán)定時任務(wù),這個相當(dāng)于web的setInterval, 回調(diào)函數(shù)是達(dá)到間隔后執(zhí)行的函數(shù)
_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事件;本來想著在圖片滑動時去清掉定時任務(wù),滑動結(jié)束后再重新初始化定時任務(wù)的,但是好像PageView和手勢有沖突,只執(zhí)行了onPanDown,onPanUpdateonPanEnd不會觸發(fā)。所以解決方案是在onPanDown時Timer.cancel清除定時,然后再初始化定時任務(wù)。

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

總結(jié)

通過做一個flutter的輪播圖,對dart語法又有了更加深入的了解,對flutter自定義組件的封裝,布局,常用的Widget也有了一定的了解。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容