Flutter实战视频-移动电商-35.列表页_上拉加载更多制作
35.列表页_上拉加载更多制作
右侧列表上拉加载配合类别的切换
上拉加载需要一个page参数,当点击大类或者小类的时候,这个page就要变成1
provide内定义参数
首先我们需要定义一个page的变量
下图是我们之前在首页的时候做的上拉加载代码,之前属性noMoreText我们没有设置值,这里我也需要把这个属性加入到provide里面去。
在大类和小类的初始化的方法内,都需要把page设置为1,然后把提示信息设置为空
然后我们需要做page增加的方法,上拉刷新的时候,这个page值是不断的增加的
再增加改变我们的noMoreText的值的方法
引入fresh插件
category_page.dart页面引入上拉刷新的插件
- import 'package:flutter_easyrefresh/easy_refresh.dart';
我们在右侧的列表类里面,在列表的地方外层嵌套easy_refresh
我们复制首页之前写好的代码过来。
中间红框内是和原来的代码,上面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=;//子类高亮索引
- String categoryId='';//大类ID 白酒的id 默认为4
- String subId='';//小类ID
- int page=;
- String noMoreText='';//显示没有数据的文字
- //大类切换逻辑
- getChildCategory(List<BxMallSubDto> list,String id){
- page=;
- noMoreText='';
- childIndex=;//每次点击大类,小类的索引都要清空掉
- categoryId=id;
- BxMallSubDto all=BxMallSubDto();
- all.mallCategoryId="";
- all.mallCategoryId="";
- all.comments="null";
- all.mallSubName='全部';
- childCategoryList=[all];
- //childCategoryList=list;
- childCategoryList.addAll(list);
- notifyListeners();//监听
- }
- //改变子类索引,indexs是从哪里来的呢?从我们具体的类中进行传递
- changeChildIndex(index,String id){
- page=;
- 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=;
- @override
- void initState() {
- super.initState();
- _getCategory();//请求接口的数据
- _getGoodsList();//参数是可选的默认是4 所以这里可以不用传值
- }
- @override
- Widget build(BuildContext context) {
- return Container(
- width: ScreenUtil().setWidth(),
- 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(),
- padding: EdgeInsets.only(left:10.0,top:10.0),
- decoration: BoxDecoration(
- color: isClick?Color.fromRGBO(, , , 1.0): Colors.white,
- border: Border(
- bottom: BorderSide(width: 1.0,color: Colors.black12)
- )
- ),
- child: Text(
- list[index].mallCategoryName,
- style: TextStyle(fontSize: ScreenUtil().setSp()),//设置字体大小,为了兼容使用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[].bxMallSubDto,list[].mallCategoryId);
- });
- }
- void _getGoodsList({String categoryId}) {
- var data={
- 'categoryId':categoryId==null?'':categoryId,//白酒的默认类别
- 'categorySubId':"",
- 'page':
- };
- 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(),
- width: ScreenUtil().setWidth(),//总的宽度是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(),
- color: isClick?Colors.pink:Colors.black
- ),
- ),
- ),
- );
- }
- void _getGoodsList(String categorySubId) {
- var data={
- 'categoryId':Provide.value<ChildCategory>(context).categoryId,//大类ID
- 'categorySubId':categorySubId,
- '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<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==){
- //列表位置,放到最上边
- scrollController.jumpTo(0.0);
- }
- } catch (e) {
- print('进入页面第一次初始化:${e}');
- }
- if(data.goodsList.length>){
- return Expanded(
- child: Container(
- width: ScreenUtil().setWidth(),
- //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的宽度 限制
- child: Image.network(newList[index].image),
- );
- }
- Widget _goodsName(List newList,index){
- return Container(
- padding: EdgeInsets.all(5.0),//上下左右都是5.0的内边距
- width: ScreenUtil().setWidth(),//370是一个大约的值
- child: Text(
- newList[index].goodsName,
- maxLines: ,//最多显示2行内容
- overflow: TextOverflow.ellipsis,
- style: TextStyle(fontSize: ScreenUtil().setSp()),//字体大小
- ),
- );
- }
- Widget _goodsPrice(List newList,index){
- return Container(
- margin: EdgeInsets.only(top:20.0),//和上面的外间距
- width: ScreenUtil().setWidth(),//370是一个大约的值
- child: Row(
- children: <Widget>[
- Text(
- '价格¥${newList[index].presentPrice}',
- style: TextStyle(color: Colors.pink,fontSize: ScreenUtil().setSp()),
- ),
- 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
Flutter实战视频-移动电商-35.列表页_上拉加载更多制作的更多相关文章
- Flutter实战视频-移动电商-32.列表页_小类高亮交互效果制作
32.列表页_小类高亮交互效果制作 点击大类右侧的横向的小类红色显示当前的小类别 解决之前溢出的问题: 先解决一个bug,之前右侧的这里设置的高度是1000,但是有不同的虚拟机和手机设别的问题造成了溢 ...
- Flutter移动电商实战 --(35)列表页_上拉加载更多制作
右侧列表上拉加载配合类别的切换 上拉加载需要一个page参数,当点击大类或者小类的时候,这个page就要变成1 provide内定义参数 首先我们需要定义一个page的变量 下图是我们之前在首页的时候 ...
- Flutter实战视频-移动电商-34.列表页_小BUG的修复
34.列表页_小BUG的修复 当高粱酒的子类没有数据返回的时候就会报错. 解决接口空数据报错的问题 没有数据的时候,给用户一个友好的提示, 我们没有数据的时候还要告诉用户,提示一下他没有数据,在我们的 ...
- Flutter实战视频-移动电商-28.列表页_商品列表后台接口调试
28.列表页_商品列表后台接口调试 主要调试商品列表页的接口 这个接口是最难的因为有大类.小类还有上拉加载 先配置接口 config/service_url.dart //const serviceU ...
- Flutter实战视频-移动电商-31.列表页_列表切换交互制作
31.列表页_列表切换交互制作 博客地址:https://jspang.com/post/FlutterShop.html#toc-c42 点击左侧的大类右边的小类也跟着变化 新建provide 要改 ...
- Flutter实战视频-移动电商-33.列表页_子类和商品列表交互效果
33.列表页_子类和商品列表交互效果 主要实现点击小类下面的列表跟着切换 获取右侧下面的列表信息,即要传递大类的id也要传递小类的,所以需要把左侧的大类的id也要Provide化 可以看下网站上的接口 ...
- Flutter实战视频-移动电商-25.列表页_使用Provide控制子类-1
25.列表页_使用Provide控制子类-1 主要是二级分类的UI布局 1分15秒 生成我们的右侧动态类 定义list变量 开始写里面的子项,把每一个小的写了 再拼成一个大的 这样我们的小类就写完了 ...
- Flutter实战视频-移动电商-26.列表页_使用Provide控制子类-2
26.列表页_使用Provide控制子类-2 主要实现功能,点击一级分类,二级分类跟着变.这里主要用哦我们的provide 新建provide provide文件夹下创建:child_category ...
- Flutter实战视频-移动电商-27.列表页_现有Bug修复和完善
27.列表页_现有Bug修复和完善 小解决小bug 默认右侧的小类没有被加载 数据加载完成后,就list的第一个子对象传递给provide进行赋值,这样右侧的小类就刷新了数据 默认加载了第一个类别 调 ...
随机推荐
- Laravel建站05--缓存、时间日期处理包
缓存 Laravel 给多种缓存系统提供丰富而统一的 API,缓存配置信息位于 config/cache.php,在这个文件中你可以为你的应用程序指定默认的缓存驱动,Laravel 支持当前流行的缓存 ...
- [概率dp] hdu 5378 Leader in Tree Land
题意: 给你一颗以1位根节点的树.我们定义对于每一个子树,节点权值最大的权值记为这个子树的权值,为你将1~n放到这个树里 满足最大权值仅仅有k个的组合数是多少. 思路: 我们能够知道以每一个节点为子树 ...
- hessian实战1
服务端: 1.新建MAVEN HessianServer 项目 2.新建接口 Basic public interface Basic { String hello(String name); Str ...
- mysql导入数据库_仅仅用frm向mysql导入表结构
网上一个连接mysql的jsp代码段,给了数据库的备份文件.可是仅仅有frm, mysql的每张表有三个文件.各自是,*.frm是描写叙述了表的结构.*.MYD保存了表的数据记录.*.MYI则是表的索 ...
- mysql 中alter语句中change跟modify的区别
mysql 中alter语句中change和modify的区别可以使用CHANGE old_col_name column_definition子句对列进行重命名.重命名时,需给定旧的和新的列名称和列 ...
- Python中十六进制和字符串的转换(转载)
调用Python内置int()函数把该字串转为数字.以下为在Python解释器编程环境下的操作示范: 把十六进制的字串转为十进制数字:Python代码>>> print int('f ...
- Android Material Design 中文版
http://www.google.com/design/spec/animation/authentic-motion.html http://www.oschina.net/question/14 ...
- 基于docker/虚拟机的esp32远程工作流
原文:基于docker/虚拟机的esp32远程工作流 工作流框图 背景说明 为什么需要这套工作流--为了满足高效和灵活的开发方式 因为我经常需要在公司和家里切换不同的电脑工作,所以编译环境需要在远程主 ...
- android android:duplicateParentState="true" "false"
今天要做一个效果.组件RelativeLayout上有两个TextView.这两个TextView具有不同的颜色值,如今要的效果是,当RelativeLayout被点击时,整个item有高亮背景. 同 ...
- php 实现简单加入购物车
今天在练习购物车以及提交订单,写的有点头晕,顺便也整理一下,这个购物车相对来说比较简单,用于短暂存储,并没有存储到数据库, 购物车对于爱网购的人来说简直是熟悉的不能再熟悉了,在写购物车之前,我们首先要 ...