Flutter實戰視頻-移動電商-35.列表頁_上拉加載更多製做

35.列表頁_上拉加載更多製做

 

右側列表上拉加載配合類別的切換json

上拉加載須要一個page參數,當點擊大類或者小類的時候,這個page就要變成1app

provide內定義參數

首先咱們須要定義一個page的變量async

下圖是咱們以前在首頁的時候作的上拉加載代碼,以前屬性noMoreText咱們沒有設置值,這裏我也須要把這個屬性加入到provide裏面去。ide

在大類和小類的初始化的方法內,都須要把page設置爲1,而後把提示信息設置爲空函數

而後咱們須要作page增長的方法,上拉刷新的時候,這個page值是不斷的增長的佈局

再增長改變咱們的noMoreText的值的方法字體

 

引入fresh插件

category_page.dart頁面引入上拉刷新的插件ui

import 'package:flutter_easyrefresh/easy_refresh.dart';

 

咱們在右側的列表類裏面,在列表的地方外層嵌套easy_refreshspa

咱們複製首頁以前寫好的代碼過來。.net

中間紅框內是和原來的代碼,上面refreshFooter部分是複製首頁的代碼過來的。下面的loadMore事件是本身寫的

再複製首頁的footerKey

 

 GlobalKey<RefreshFooterState> _footerkey=new GlobalKey<RefreshFooterState>();

 

這樣key這裏就不報錯了。

 

noMoreText用狀態 管理裏面的值

noMoreText: Provide.value<ChildCategory>(context).noMoreText,

 

 

效果展現

loadMore回調函數補充完整

上拉加載更多和咱們加載大類和小類是同樣的 咱們複製右側的列表的數據獲取的方法

下圖是複製的右側加載列表數據的方法

 

 

下面這裏,由於咱們是不斷的累計list的數據的 因此不能再使用等號了。

修改成使用addAll的方法

調用咱們獲取數據的方法

修正一個地方,這個方法添加的地方是在最後一個花括號結束的上方 複製這個getMoreList的方法

 

有了上拉刷新的效果。可是點擊小類的時候列表數據,不變化了

 

 

 

修正一個錯誤的地方

 

上拉刷新的效果

 

 

page須要++

咱們在調用上拉刷險的時候,沒有調用page++

 

存在問題

當咱們一個類別上拉刷新了幾回後,滾動條滾動到最下面了。當咱們再去點擊別的大類的時候,滾動條仍是在這個位置上。滾動條沒有滾動到最上面

只要切換大類的是時候,就返回咱們的頂部,好用scrollController的jumpTo方法 跳轉到0.0的位置

 

最終代碼:

provide/child_category.dart

import 'package:flutter/material.dart';
import '../model/category.dart';

class ChildCategory with ChangeNotifier{
 List<BxMallSubDto> childCategoryList=[];
 int childIndex=0;//子類高亮索引
 String categoryId='4';//大類ID 白酒的id 默認爲4
 String subId='';//小類ID
 int page=1;
 String noMoreText='';//顯示沒有數據的文字
  //大類切換邏輯
  getChildCategory(List<BxMallSubDto> list,String id){
    page=1;
    noMoreText='';
    childIndex=0;//每次點擊大類,小類的索引都要清空掉
    categoryId=id;
    BxMallSubDto all=BxMallSubDto();
    all.mallCategoryId="00";
    all.mallCategoryId="00";
    all.comments="null";
    all.mallSubName='所有';
    childCategoryList=[all];
    //childCategoryList=list;
    childCategoryList.addAll(list);
    notifyListeners();//監聽
  }
  //改變子類索引,indexs是從哪裏來的呢?從咱們具體的類中進行傳遞
  changeChildIndex(index,String id){
    page=1;
    noMoreText='';
    childIndex=index;//把傳遞過來的index賦值給咱們的childIndex
    subId=id;
    notifyListeners();//通知
  }
  //增長Page的方法
  addPage(){
    page++;
    //notifyListeners();//這裏不須要通知,由於咱們只是page+1了並無頁面數據上的變化
  }
  //改變noMore的方法
  changeNoMore(String text){
    noMoreText=text;
    notifyListeners();//通知
  }
}

 

 

provide/category_goods_list.dart

import 'package:flutter/material.dart';
import '../model/categoryGoodsList.dart';

class CategoryGoodsListProvide with ChangeNotifier{
 List<CategoryListData> goodsList=[];
 //點擊大類時候更換商品列表
 getGoodsList(List<CategoryListData> list){
   goodsList=list;
   notifyListeners();
 }

 getMoreList(List<CategoryListData> list){
   goodsList.addAll(list);
   notifyListeners();
 }

}

 

 

 

import 'package:flutter/material.dart';
import '../service/service_method.dart';
import 'dart:convert';
import '../model/category.dart';
import '../model/categoryGoodsList.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:provide/provide.dart';
import '../provide/child_category.dart';
import '../provide/category_goods_list.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart';

class CategoryPage extends StatefulWidget {
  @override
  _CategoryPageState createState() => _CategoryPageState();
}

class _CategoryPageState extends State<CategoryPage> {
  @override
  Widget build(BuildContext context) {
    //_getCategory();
    return Scaffold(
      appBar: AppBar(title: Text('商品分類'),),
      body: Container(
        child: Row(
          children: <Widget>[
            LeftCategoryNav(),
            Column(
              children: <Widget>[
                RightCategoryNav(),
                CategoryGoodsList()
              ],
            )
          ],
        ),
      ),
    );
  }

 
}

//左側大類導航
class LeftCategoryNav extends StatefulWidget {
  @override
  _LeftCategoryNavState createState() => _LeftCategoryNavState();
}

class _LeftCategoryNavState extends State<LeftCategoryNav> {
  List list=[];
  var listIndex=0;
  @override
  void initState() { 
    super.initState();
    _getCategory();//請求接口的數據
    _getGoodsList();//參數是可選的默認是4 因此這裏能夠不用傳值
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      width: ScreenUtil().setWidth(180),
      decoration: BoxDecoration(
        border: Border(
          right: BorderSide(width:1.0,color: Colors.black12),//有邊框
        )
      ),
      child: ListView.builder(
        itemCount: list.length,
        itemBuilder: (contex,index){
          return _leftInkWell(index);
        },
      ),
    );
  }

  Widget _leftInkWell(int index){
    bool isClick=false;
    isClick=(index==listIndex)?true:false;
    return InkWell(
      onTap: (){
        setState(() {
         listIndex=index; 
        });
        var childList=list[index].bxMallSubDto;//當前大類的子類的列表
        var categoryId=list[index].mallCategoryId;//大類的id
        Provide.value<ChildCategory>(context).getChildCategory(childList,categoryId);
        _getGoodsList(categoryId:categoryId);
      },
      child: Container(
        height: ScreenUtil().setHeight(100),
        padding: EdgeInsets.only(left:10.0,top:10.0),
        decoration: BoxDecoration(
          color: isClick?Color.fromRGBO(236, 236, 236, 1.0): Colors.white,
          border: Border(
            bottom: BorderSide(width: 1.0,color: Colors.black12)
          )
        ),
        child: Text(
          list[index].mallCategoryName,
          style: TextStyle(fontSize: ScreenUtil().setSp(28)),//設置字體大小,爲了兼容使用setSp
        ),
      ),
    );
  }
   void _getCategory() async{
    await request('getCategory').then((val){
      var data=json.decode(val.toString());
      //print(data);
      CategoryModel category= CategoryModel.fromJson(data);
      setState(() {
       list=category.data; 
      });
      Provide.value<ChildCategory>(context).getChildCategory(list[0].bxMallSubDto,list[0].mallCategoryId);
    });
  }

  void _getGoodsList({String categoryId}) {
    var data={
      'categoryId':categoryId==null?'4':categoryId,//白酒的默認類別
      'categorySubId':"",
      'page':1
    };
    request('getMallGoods',formData: data).then((val){
      var data=json.decode(val.toString());
      CategoryGoodsListModel goodsList=CategoryGoodsListModel.fromJson(data);//這樣就從json'轉換成了model類
      //print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>:${goodsList.data[0].goodsName}');
      // setState(() {
      //  list=goodsList.data; 
      // });
      Provide.value<CategoryGoodsListProvide>(context).getGoodsList(goodsList.data);
    });
  }
}

class RightCategoryNav extends StatefulWidget {
  @override
  _RightCategoryNavState createState() => _RightCategoryNavState();
}

class _RightCategoryNavState extends State<RightCategoryNav> {
  //List list = ['名酒','寶丰','北京二鍋頭','捨得','五糧液','茅臺','散白'];
  @override
  Widget build(BuildContext context) {
    return Provide<ChildCategory>(
      builder: (context,child,childCategory){
        return  Container(
          height: ScreenUtil().setHeight(80),
          width: ScreenUtil().setWidth(570),//總的寬度是750 -180
          decoration: BoxDecoration(
            color: Colors.white,//白色背景
            border: Border(
              bottom: BorderSide(width: 1.0,color: Colors.black12)//邊界線
            )
          ),
          child: ListView.builder(
            scrollDirection: Axis.horizontal,
            itemCount: childCategory.childCategoryList.length,
            itemBuilder: (context,index){
              return _rightInkWell(index,childCategory.childCategoryList[index]);
            },
          ),
        );
      }
    );
  }

  Widget _rightInkWell(int index,BxMallSubDto item){
    bool isClick=false;
    isClick=(index==Provide.value<ChildCategory>(context).childIndex)?true:false;

    return InkWell(
      onTap: (){
        Provide.value<ChildCategory>(context).changeChildIndex(index,item.mallSubId);
        _getGoodsList(item.mallSubId);
      },//事件留空
      child: Container(//什麼都加一個container,這樣好佈局
        padding: EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 10.0),//上下是10 左右是5.0
        child: Text(
          item.mallSubName,
          style:TextStyle(
            fontSize: ScreenUtil().setSp(28),
            color: isClick?Colors.pink:Colors.black
          ),
        ),
      ),
    );
  }
  void _getGoodsList(String categorySubId) {
    var data={
      'categoryId':Provide.value<ChildCategory>(context).categoryId,//大類ID
      'categorySubId':categorySubId,
      'page':1
    };
    request('getMallGoods',formData: data).then((val){
      var data=json.decode(val.toString());
      CategoryGoodsListModel goodsList=CategoryGoodsListModel.fromJson(data);//這樣就從json'轉換成了model類
      if(goodsList.data==null){
        Provide.value<CategoryGoodsListProvide>(context).getGoodsList([]);
      }else{
        Provide.value<CategoryGoodsListProvide>(context).getGoodsList(goodsList.data);
      }
      
    });
  }
}

//商品列表 ,能夠上拉加載
class CategoryGoodsList extends StatefulWidget {
  @override
  _CategoryGoodsListState createState() => _CategoryGoodsListState();
}

class _CategoryGoodsListState extends State<CategoryGoodsList> {
   GlobalKey<RefreshFooterState> _footerkey=new GlobalKey<RefreshFooterState>();
   var scrollController=new ScrollController();
  @override
  void initState() {
    //_getGoodsList();
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Provide<CategoryGoodsListProvide>(
      builder: (context,child,data){
        try {
          if(Provide.value<ChildCategory>(context).page==1){
            //列表位置,放到最上邊
            scrollController.jumpTo(0.0);
          }
        } catch (e) {
          print('進入頁面第一次初始化:${e}');
        }
        if(data.goodsList.length>0){
            return  Expanded(
              child: Container(
                width: ScreenUtil().setWidth(570),
                //height: ScreenUtil().setHeight(974),
                child: EasyRefresh(
                   refreshFooter: ClassicsFooter(
                      key: _footerkey,
                      bgColor: Colors.white,//背景顏色
                      textColor: Colors.pink,//粉紅色
                      moreInfoColor: Colors.white,
                      showMore: true,
                      noMoreText: Provide.value<ChildCategory>(context).noMoreText,//具體也不知道到沒到底 因此這裏直接設置爲空就再也不顯示了
                      moreInfo: '加載中',
                      loadReadyText: '上拉加載......',//網上拉 顯示的文字
                    ),
                    child:   ListView.builder(
                      controller: scrollController,
                      itemCount: data.goodsList.length,
                      itemBuilder: (contex,index){
                        return _listWidget(data.goodsList,index);
                      },
                    ),
                    loadMore: () async{
                      print('上拉加載更多......');
                      _getMoreList();
                    },
                )
              ),
            );
        }else{
          return Text('暫時沒有數據');
        }
       
      },
    );
  }
   
  void _getMoreList() {
     Provide.value<ChildCategory>(context).addPage();
      var data={
        'categoryId':Provide.value<ChildCategory>(context).categoryId,//大類ID
        'categorySubId':Provide.value<ChildCategory>(context).subId,
        'page':Provide.value<ChildCategory>(context).page
      };
      request('getMallGoods',formData: data).then((val){
        var data=json.decode(val.toString());
        CategoryGoodsListModel goodsList=CategoryGoodsListModel.fromJson(data);//這樣就從json'轉換成了model類
        if(goodsList.data==null){
          Provide.value<ChildCategory>(context).changeNoMore('沒有更多了');
        }else{
          Provide.value<CategoryGoodsListProvide>(context).getMoreList(goodsList.data);
        }
        
      });
    }


  //}
  

  Widget _goodsImage(List newList,index){
    return Container(
      width: ScreenUtil().setWidth(200),//設置200的寬度 限制
      child: Image.network(newList[index].image),
    );
  }
  Widget _goodsName(List newList,index){
    return Container(
      padding: EdgeInsets.all(5.0),//上下左右都是5.0的內邊距
      width: ScreenUtil().setWidth(370),//370是一個大約的值
      child: Text(
        newList[index].goodsName,
        maxLines: 2,//最多顯示2行內容
        overflow: TextOverflow.ellipsis,
        style: TextStyle(fontSize: ScreenUtil().setSp(28)),//字體大小
      ),
    );
  }

  Widget _goodsPrice(List newList,index){
    return Container(
      margin: EdgeInsets.only(top:20.0),//和上面的外間距
      width: ScreenUtil().setWidth(370),//370是一個大約的值
      child: Row(
        children: <Widget>[
          Text(
            '價格¥${newList[index].presentPrice}',
            style: TextStyle(color: Colors.pink,fontSize: ScreenUtil().setSp(30)),
          ),
          Text(
            '價格¥${newList[index].oriPrice}',
            style: TextStyle(
              color: Colors.black26,
              decoration: TextDecoration.lineThrough
            ),//刪除線的樣式
          )
        ],
      ),
    );
  }

  Widget _listWidget(List newList,int index){
    return InkWell(
      onTap: (){},
      child: Container(
        padding: EdgeInsets.only(top:5.0,bottom:5.0),
        decoration: BoxDecoration(
          color: Colors.white,
          border: Border(
            bottom: BorderSide(width: 1.0,color: Colors.black12)
          )
        ),
        child: Row(
          children: <Widget>[
            _goodsImage(newList,index),
            Column(
              children: <Widget>[
                _goodsName(newList,index),
                _goodsPrice(newList,index)
              ],
            )
          ],
        ),
      ),
    );
  }
}
category_page.dart
相關文章
相關標籤/搜索