Flutter实现可循环轮播图效果
效果图
壹、控件分解图
贰、代码实现
贰点壹、构建根布局
新建adpicturewidget继承自statefulwidget,新建_adpicturewidgetstate
类继承自state<adpicturewidget>
,根布局为stack,代码如下:
class adpicturewidget extends statefulwidget { @override _adpicturewidgetstate createstate() => _adpicturewidgetstate(); } class _adpicturewidgetstate extends state<adpicturewidget>{ @override widget build(buildcontext context) { return stack( children: <widget>[ ... ], ); } }
贰点贰、构建pageview
pageview类似于android里的viewpager,我们可以使用pagecontroller控制pageview 的滑动行为,比如设置滑动动画、令其滑动到指定的页面等等。可以通过设置onpagechanged
来监听页面的滑动,相当于android里的pagelistener。每一个page里的布局可以通过children属性进行设置,例子中每一个page里包含一张图片,图片是通过网络来加载的。代码如下:
class _adpicturewidgetstate extends state<adpicturewidget>{ pagecontroller _pagecontroller = pagecontroller(); list _adpictures = []; @override void dispose() { _pagecontroller.dispose(); super.dispose(); } @override widget build(buildcontext context) { return stack( children: <widget>[ pageview( children: _adpictures.map((json) { var adpicture = adpicture.fromjson(json);//可以先忽略这个实体类 return image.network( adpicture.imageurl, fit: boxfit.fill,//使照片占满整个屏幕 ); }).tolist(), onpagechanged: _onpagechanged, controller: _pagecontroller, ), ], ); } void _onpagechanged(int index) { ... } }
贰点叁、构建下方的indicator布局
屏幕下方的一行指示小圆点可以直接使用flutter的tabpageselector搞定,使用align控制其显示在屏幕的下方。我们只需要使用tabpageselector的三个属性即可,通过color属性设置其未被选中时的颜色,通过selectedcolor设置选中时的颜色,那如何控制选中还是未被选中呢,答案是它的controller属性,我们直接new出一个tabcontroller类,将其赋值给controller属性即可,代码如下:
class _adpicturewidgetstate extends state<adpicturewidget> with singletickerproviderstatemixin { tabcontroller _tabcontroller; ... @override void initstate() { _tabcontroller = tabcontroller(length: 0, vsync: this); super.initstate(); } @override void dispose() { ... _tabcontroller.dispose(); super.dispose(); } @override widget build(buildcontext context) { return stack( children: <widget>[ pageview( ... ), align( alignment: alignment(0.0, 0.5), child: tabpageselector( color: colors.white, selectedcolor: colors.black, controller: _tabcontroller, ), ), ], ); }
贰点肆、pageview和tabpageselector联动 & 定时自动翻页
二者的联动很简单,在pageview的滑动回调里调用_tabcontroller的animateto方法即可实现二者的联动。如果需要定时翻页,则需要使用到一个timer的类,详细代码如下:
const timeout = const duration(seconds: 2); class _adpicturewidgetstate extends state<adpicturewidget> with singletickerproviderstatemixin { ... timer _timer; int _index = 0; @override void initstate() { ... _timer = timer.periodic(timeout, _handletimeout);//一创建定时器就启动了,每过timeout时间就会调用_handletimeout这个回调。 super.initstate(); } @override void dispose() { ... _timer.cancel(); super.dispose(); } _handletimeout(timer timer) { _index++; _pagecontroller.animatetopage( _index % (_adpictures.length),//跳转到的位置 duration: duration(milliseconds: 16),//跳转的间隔时间 curve: curves.fastoutslowin,//跳转动画 ); _tabcontroller.animateto(_index % (_adpictures.length)); }
贰点五、循环翻页实现
假设只有三页,实现循环播放的原理是在原来的数据基础上,在最开始插入一张原本的尾页,在最末尾插入一张原本的首页(看上面两张图也许更形象),当用户滑动到现在的尾页时,程序自动的将其滑动到现在的第二页,滑动的很快对用户来说是无感之的,同理,当用户滑动到现在的首页时,程序自动滑动到现在的倒数第二页。这种方法在android里也是挺常用的。
叁、可运行的完整代码
•依赖的第三方库:
dio: 1.0.6
json_annotation: ^2.0.0
•代码及文件名:
///文件名:adpicturewidget.dart class adpicturewidget extends statefulwidget { @override _adpicturewidgetstate createstate() => _adpicturewidgetstate(); } const timeout = const duration(seconds: 2); class _adpicturewidgetstate extends state<adpicturewidget> with singletickerproviderstatemixin { tabcontroller _tabcontroller; pagecontroller _pagecontroller = pagecontroller(); timer _timer; list _adpictures = []; int _index = 0; @override void initstate() { _tabcontroller = tabcontroller(length: 0, vsync: this); _timer = timer.periodic(timeout, _handletimeout); loadadpictures(); super.initstate(); } @override void dispose() { _tabcontroller.dispose(); _timer.cancel(); _pagecontroller.dispose(); super.dispose(); } @override widget build(buildcontext context) { return stack( children: <widget>[ pageview( children: _adpictures.map((json) { var adpicture = adpicture.fromjson(json); return image.network(adpicture.imageurl, fit: boxfit.fill); }).tolist(), onpagechanged: _onpagechanged, controller: _pagecontroller, ), align( alignment: alignment(0.0, 0.5), child: tabpageselector( color: colors.white, selectedcolor: colors.black, controller: _tabcontroller, ), ), ], ); } _handletimeout(timer timer) { if (_adpictures.length - 2 != 0) { _index++; _pagecontroller.animatetopage( _index % (_adpictures.length - 2), duration: duration(milliseconds: 16), curve: curves.fastoutslowin, ); } } void _onpagechanged(int index) { _index = index; if (index == 0) { _tabcontroller.animateto(_tabcontroller.length - 1); _pagecontroller.jumptopage(_adpictures.length - 2); } else if (index == _adpictures.length - 1) { _tabcontroller.animateto(0); _pagecontroller.jumptopage(1); } else { _tabcontroller.animateto(index - 1); } } void loadadpictures() async { dio dio = dio(); response<list> response = await dio .get("http://www.wanandroid.com/tools/mockapi/2511/getadpictures"); list res = response.data; if (res.length != 0) { res.insert(0, res[res.length - 1]); res.add(res[1]); setstate(() { _adpictures = res; _pagecontroller.jumptopage(1); _tabcontroller = tabcontroller(length: _adpictures.length - 2, vsync: this); }); } } } ///文件名:adpicture.dart library adpicture; import 'package:json_annotation/json_annotation.dart'; part 'adpicture.g.dart'; ///首页轮播图 @jsonserializable() class adpicture { final string imageurl; //图片链接 adpicture({ this.imageurl, }); factory adpicture.fromjson(map<string, dynamic> json) => _$adpicturefromjson(json); } ///文件名:adpicture.g.dart part of adpicture; adpicture _$adpicturefromjson(map<string, dynamic> json) { return adpicture(imageurl: json['imageurl'] as string); } map<string, dynamic> _$adpicturetojson(adpicture instance) => <string, dynamic>{ 'imageurl': instance.imageurl, };
总结
以上所述是小编给大家介绍的flutter实现可循环轮播图效果,希望对大家有所帮助