美文网首页Flutter教程网
Flutter 使用pageController制作无限滚动栏

Flutter 使用pageController制作无限滚动栏

作者: 写一点是一点 | 来源:发表于2019-07-17 23:04 被阅读1次

    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<Widget> 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);
         }
       });
    }
    
    

    相关文章

      网友评论

        本文标题:Flutter 使用pageController制作无限滚动栏

        本文链接:https://www.haomeiwen.com/subject/dsyhlctx.html