您的位置:首页 > 其它

FLUTTER 无限滚动栏 banner方案

2019-07-09 22:47 1096 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/importIng/article/details/95241595

BANNER 是应用中最常见的复合控件之一,当然也有无数种功能齐全好看好使的第三方工具。这里写一个最简单的三页式BANNER,了解一下PageController,Timer的用法以及一些简单的方法封装

基本思路

  1. 使用PageController设置一个三页翻页控件
  2. 显示中页 并给三页按照顺序放置BANNER控件
  3. 在滚动到前/后页的时刻回到中页并同时更换三页的控件内容
  4. 添加自动滚动的定时器

实现

  1. 首先创建创建一个StatefulWidget 并令其驻留在内存中以保存滚动状态

    flutter
    class _BannerItemState extends State<BannerItem> with AutomaticKeepAliveClientMixin{
    @override
    bool get wantKeepAlive => true;
  2. 初始化一个数据源,这里我是用array存一组IMAGE作为数据源,控件的内容从数组中获取,只需更新数组就可以了。 默认状态可以放一个占位图,这里我就放放一个空白控件当占位
    //数据源
    List imageList = [new Container()];

  3. 布局 界面上使用一个有三个 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;

}

布局,前中后页获取就完成了

  1. 在滚动结束的事件回到中页并完成_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;
}
}
});
}
  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);
}
});
  1. 添加自动滚动的定时器,记得在销毁的时候撤掉定时器
_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();
}
  1. 最后从你的数据源获取数据并替换数据源数组即可
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);
}
});
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: