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

1.了解需求
- 輪播圖具有自動翻頁
- 可以手勢拖動翻頁,點擊事件
- 有個指示器
- 輪播圖的一些基礎(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,onPanUpdate和onPanEnd不會觸發(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),
),
],
)

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