BANNER 是应用中最常见的复合控件之一,当然也有无数种功能齐全好看好使的第三方工具。这里写一个最简单的三页式BANNER,了解一下PageController,Timer的用法以及一些简单的方法封装
基本思路
- 使用PageController设置一个三页翻页控件
- 显示中页 并给三页按照顺序放置BANNER控件
- 在滚动到前/后页的时刻回到中页并同时更换三页的控件内容
- 添加自动滚动的定时器
实现
-
首先创建创建一个StatefulWidget 并令其驻留在内存中以保存滚动状态
flutter class _BannerItemState extends State<BannerItem> with AutomaticKeepAliveClientMixin{ @override bool get wantKeepAlive => true;
-
初始化一个数据源,这里我是用array存一组IMAGE作为数据源,控件的内容从数组中获取,只需更新数组就可以了。 默认状态可以放一个占位图,这里我就放放一个空白控件当占位
//数据源
List<Widget> imageList = [new Container()]; -
布局 界面上使用一个有三个 child的pageview即可,中间的控件在底部放上按钮以传出点击事件
//中间页下标
int _cur = 0;
PageController _pageController = new PageController(initialPage: 1,
keepPage: true,viewportFraction: 1.0);
@override
Widget build(BuildContext context) {
// TODO: implement build
super.build(context);
return new Container(
height: 150,
color:SkinConfig.instance.randomColor(),
child:getPageView(),
alignment: Alignment.center,
);
}
Widget getPageView(){
return PageView(
children: <Widget> [
new Container(color: SkinConfig.instance.mainBGColor(),
alignment: Alignment.center,
child: imageList[preNum()] ,
padding: EdgeInsets.all(0),),
new Container(color: SkinConfig.instance.mainBGColor(),
alignment: Alignment.center,
child: new FlatButton(onPressed: btnTouched,
child: imageList[_cur],padding: EdgeInsets.all(0),),
padding: EdgeInsets.all(0), ),
new Container(color: SkinConfig.instance.mainBGColor(),
alignment: Alignment.center,
child: imageList[nextNum()] ,
padding: EdgeInsets.all(0),),
],
scrollDirection: Axis.horizontal,
// onPageChanged: pageChanged,
controller: _pageController,
);
}
//前页
int preNum(){
return _cur - 1>=0?_cur-1:imageList.length - 1;
}
//后页
int nextNum(){
return _cur + 1 <imageList.length ?_cur + 1:0;
}
布局,前中后页获取就完成了
- 在滚动结束的事件回到中页并完成_cur的切换
void changePage(int pageCount){
//向后滚动
setState(() {
if(pageCount == 2){
_cur++;
if(_cur == imageList.length){
_cur = 0;
}
}
//向前滚动
if(pageCount == 0){
_cur--;
if(_cur == -1){
_cur = imageList.length - 1;
}
}
});
}
- 监听滚动事件,在滚动到前/后页的时候回到中页并切换数据
_pageController.addListener((){
if( _pageController.offset <= 0 ){
_pageController.jumpToPage(1);
changePage(0);
}
if( _pageController.offset >= 2 * MediaQuery.of(context).size.width ){
_pageController.jumpToPage(1);
changePage(2);
}
});
- 添加自动滚动的定时器,记得在销毁的时候撤掉定时器
_timer = Timer.periodic(const Duration(seconds: 5), (Timer timer){
_pageController.animateToPage(2, duration: const Duration(seconds: 2), curve: Curves.fastOutSlowIn);
});
//
@override
void dispose() {
_timer.cancel();
// TODO: implement dispose
super.dispose();
}
- 最后从你的数据源获取数据并替换数据源数组即可
Future<Null>requestData()async{
print('banner request');
HttpClient httpClient = new HttpClient();
Uri uri=Uri(scheme: "http", host: URLbaseWWW,path:PATHBanner , queryParameters: {
'id' : 'NEWS_POP'
});
HttpClientRequest request = await httpClient.getUrl(uri);
HttpClientResponse response = await request.close();
String responseBody = await response.transform(utf8.decoder).join();
Map result = json.decode(responseBody);
List dataList = result['Data'];
//取得数据
setState(() {
for(var i = 0 ;i < dataList.length;i++){
Map dict = dataList[i];
String path = 'http://' + URLbaseWWW + dict['BannerImage'];
//将数据添加到数据源中
imageList.add(new Image.network(path,height: MediaQuery.of(context).size.width / 16 * 9 ,width:MediaQuery.of(context).size.width,fit: BoxFit.fill,));
}
//移除数据源中不需要的元素
while(imageList.length > dataList.length){
imageList.removeAt(0);
}
});
}
网友评论