輪播圖簡直是不要太常見的功能了。今天來看一下在Flutter中是怎麼實現的。
效果
關於Swiper
flutter最強大的siwiper, 多種佈局方式,無限輪播,Android和IOS雙端適配.
github:https://github.com/best-flutter/flutter_swiper
引用:
flutter_swiper : ^1.1.6
示例並講解
廢話不多說,直接拿效果圖講解。
注意看上圖中紅色標記的部分:
- 1,分頁控制器,即點擊到下一頁或上一頁,效果等於觸摸滑動
- 2,不顯示的item在兩側縮小顯示
- 3,指示器中,選中的要偏大一些
ok,圍繞着基礎使用 擴展一些常見的功能。
基礎使用
child: Swiper(
itemCount: bannerDatas.length,
//item數量
itemBuilder: (BuildContext context, int index) {
//item構建
return new Image.network(
"https://www.wanandroid.com/blogimgs/acc23063-1884-4925-bdf8-0b0364a7243e.png",
fit: BoxFit.fill,
);
},
),
基礎使用兩個參數就行了,
- itemCount: item數量
- itemBuilder: item構建
分頁控制器
這個其實一般用的不多。。
添加一個control
屬性即可
control: new SwiperControl(),//默認分頁按鈕
看一下源碼:
const SwiperControl(
{this.iconPrevious: Icons.arrow_back_ios,
this.iconNext: Icons.arrow_forward_ios,
this.color,
this.disableColor,
this.key,
this.size: 30.0,
this.padding: const EdgeInsets.all(5.0)});
可以修改圖標、顏色、大小等等,比如
control: new SwiperControl(size: 20),
顯示樣式
效果圖中可以看出,不顯示的item是在兩側縮小顯示的,那這種樣式怎麼實現呢?
添加兩個參數
viewportFraction: 0.8,
scale: 0.9,
- viewportFraction:視圖寬度,即顯示的item的寬度屏佔比
- scale:兩側item的縮放比
參數在0到1之間。
指示器
pagination: new SwiperPagination(),//默認指示器
默認即圓點的方式,
其他樣式:
class SwiperPagination extends SwiperPlugin {
/// dot style pagination
static const SwiperPlugin dots = const DotSwiperPaginationBuilder();
/// fraction style pagination
static const SwiperPlugin fraction = const FractionPaginationBuilder();
static const SwiperPlugin rect = const RectSwiperPaginationBuilder();
....
}
上面源碼可以看到,SwiperPagination
繼承自SwiperPlugin
,
然後 dots 其實是 DotSwiperPaginationBuilder
,DotSwiperPaginationBuilder也是繼承自SwiperPlugin
進一步查看源碼:
class DotSwiperPaginationBuilder extends SwiperPlugin {
.....
const DotSwiperPaginationBuilder(
{this.activeColor,
this.color,
this.key,
this.size: 10.0,
this.activeSize: 10.0,
this.space: 3.0});
....
我們可以看到顏色和大小都有選中和未選中之分,還可以設置間距,那我們就可以輕鬆的實現上圖中的效果了
pagination: new SwiperPagination(
builder: new DotSwiperPaginationBuilder(size: 8, activeSize: 12),
),
只簡單改一下size就ok了
點擊事件
onTap,接收一個下標參數:
onTap: (int index) {
//點擊事件,返回下標
print("index-----" + index.toString());
},
高度自適應
如何做到banner高度自適應呢,目前的解決方案就是動態計算。
外層用Container
包裹,然後設置Container的寬高。
Container(
//屏幕寬度
width: MediaQuery.of(context).size.width,
//1.8是banner寬高比,0.8是viewportFraction的值
height: MediaQuery.of(context).size.width / 1.8 * 0.8,
child: Swiper(
...
),
),
完整代碼
Container(
width: MediaQuery.of(context).size.width,
//1.8是banner寬高比,0.8是viewportFraction的值
height: MediaQuery.of(context).size.width / 1.8 * 0.8,
child: Swiper(
itemCount: bannerDatas.length,
//item數量
itemBuilder: (BuildContext context, int index) {
//item構建
return new Image.network(
bannerDatas[index].imagePath,
fit: BoxFit.fill,
);
},
autoplay: true,
//是否自動播放
autoplayDelay: 3000,
//自動播放延遲
autoplayDisableOnInteraction: true,
//觸發時是否停止播放
duration: 600,
//動畫時間
control: new SwiperControl(),
//默認分頁按鈕
//默認指示器
pagination: new SwiperPagination(
// SwiperPagination.fraction 數字1/5,默認點
builder: new DotSwiperPaginationBuilder(size: 8, activeSize: 12),
),
viewportFraction: 0.8,
//視圖寬度,即顯示的item的寬度屏佔比
scale: 0.9,
//兩側item的縮放比
onTap: (int index) {
//點擊事件,返回下標
print("index-----" + index.toString());
},
),
),
Github:https://github.com/yechaoa/wanandroid_flutter
swiper 嵌套在listview(scrollview)中 的時候會報
ScrollController not attached to any scroll views.
異常,還未解決,解決的還請告知一下
詳細屬性
基本參數
參數 | 默認值 | 描述 |
---|---|---|
scrollDirection | Axis.horizontal | 滾動方向,設置爲Axis.vertical如果需要垂直滾動 |
loop | true | 無限輪播模式開關 |
index | 0 | 初始的時候下標位置 |
autoplay | false | 自動播放開關. |
onIndexChanged | void onIndexChanged(int index) | 當用戶手動拖拽或者自動播放引起下標改變的時候調用 |
onTap | void onTap(int index) | 當用戶點擊某個輪播的時候調用 |
duration | 300.0 | 動畫時間,單位是毫秒 |
pagination | null | 設置 new SwiperPagination() 展示默認分頁指示器 |
control | null | 設置 new SwiperControl() 展示默認分頁按鈕 |
autoplayDely | 3000 | 自動播放延遲毫秒數. |
autoplayDisableOnInteraction | true | 當用戶拖拽的時候,是否停止自動播放. |
分頁指示器
分頁指示器繼承自 SwiperPlugin
,SwiperPlugin
爲 Swiper
提供額外的界面.設置爲new SwiperPagination()
展示默認分頁.
參數 | 默認值 | 描述 |
---|---|---|
alignment | Alignment.bottomCenter | 如果要將分頁指示器放到其他位置,那麼可以修改這個參數 |
margin | const EdgeInsets.all(10.0) | 分頁指示器與容器邊框的距離 |
builder | SwiperPagination.dots | 目前已經定義了兩個默認的分頁指示器樣式: SwiperPagination.dots 、 SwiperPagination.fraction ,都可以做進一步的自定義. |
如果需要定製自己的分頁指示器,那麼可以這樣寫:
new Swiper(
...,
pagination:new SwiperCustomPagination(
builder:(BuildContext context, SwiperPluginConfig config){
return new YourOwnPaginatipon();
}
)
);
控制按鈕
控制按鈕組件也是繼承自 SwiperPlugin
,設置 new SwiperControl()
展示默認控制按鈕.
參數 | 默認值 | 描述 |
---|---|---|
iconPrevious | Icons.arrow_back_ios | 上一頁的IconData |
iconNext | Icons.arrow_forward_ios | 下一頁的IconData |
color | Theme.of(context).primaryColor | 控制按鈕顏色 |
size | 30.0 | 控制按鈕的大小 |
padding | const EdgeInsets.all(5.0) | 控制按鈕與容器的距離 |
控制器(SwiperController)
SwiperController
用於控制 Swiper的index
屬性, 停止和開始自動播放. 通過 new SwiperController()
創建一個SwiperController實例,並保存,以便將來能使用。
方法 | 描述 |
---|---|
void move(int index, {bool animation: true}) | 移動到指定下標,設置是否播放動畫 |
void next({bool animation: true}) | 下一頁 |
void previous({bool animation: true}) | 上一頁 |
void startAutoplay() | 開始自動播放 |
void stopAutoplay() | 停止自動播放 |
構建你自己的動畫十分簡單:
new Swiper(
layout: SwiperLayout.CUSTOM,
customLayoutOption: new CustomLayoutOption(
startIndex: -1,
stateCount: 3
).addRotate([
-45.0/180,
0.0,
45.0/180
]).addTranslate([
new Offset(-370.0, -40.0),
new Offset(0.0, 0.0),
new Offset(370.0, -40.0)
]),
itemWidth: 300.0,
itemHeight: 200.0,
itemBuilder: (context, index) {
return new Container(
color: Colors.grey,
child: new Center(
child: new Text("$index"),
),
);
},
itemCount: 10)
CustomLayoutOption
被設計用來描述佈局和動畫,很簡單的可以指定每一個元素的狀態.
new CustomLayoutOption(
startIndex: -1, /// 開始下標
stateCount: 3 /// 下面的數組長度
).addRotate([ // 每個元素的角度
-45.0/180,
0.0,
45.0/180
]).addTranslate([ /// 每個元素的偏移
new Offset(-370.0, -40.0),
new Offset(0.0, 0.0),
new Offset(370.0, -40.0)
])