上期实现了一个网络轮播图的效果,自定义了一个轮播图组件,继承自StatefulWidget,我们知道Flutter中并没有像Android中activity的概念。页面见的跳转是通过路由从一个全屏组件跳转到另外的一个全屏组件,那如果我想在A组件中更新B组件的数据应该怎么实现呢?

今天我们来实现一个支持筛选的列表页面。前面我们已经实现来一个支持下拉刷新和上拉加载更多的列表组件,这里就不在做更多介绍来,效果图如下:



通过点击左滑菜单筛选列表的数据。由于列表在之前的一篇文章已经说明过Flutter学习四之实现一个支持刷新加载的列表,所以这里就直接上列表的代码:我们将列表定义程一个组件,方便,页面引用,列表的请求也放在组件内部。

class ArticleListBaseWidget extends StatefulWidget {
int cid = 0; //文章分类的id
@override
State<StatefulWidget> createState() {
return ArticleListBaseState();
} ArticleListBaseWidget({this.cid});
} class ArticleListBaseState extends State<ArticleListBaseWidget> {
RefreshController refreshController =
RefreshController(initialRefresh: true);
int pageNum = 0;
List<TopArticleBeanData> _articles = []; void onRefresh() {
pageNum = 0;
getArticle(true, getApiName());
} void loadMore() {
pageNum++;
getArticle(false, getApiName());
} //根据cid参数来处理apiName,如果没有传cid参数进来表示不支持分类筛选。
String getApiName() {
String apiName = "";
if (widget.cid > 0) {
apiName = "article/list/$pageNum/json?cid=${widget.cid}";
} else {
apiName = "article/list/$pageNum/json";
}
print("apiName=$apiName");
return apiName;
} ///置顶文章
void getArticle(bool isRefresh, String apiName) async {
///文章接口请求
dio.get(apiName).then((value) {
///文章实体解析
ArticleListEntityEntity articleBeanEntity =
ArticleListEntityEntity().fromJson(jsonDecode(value.toString()));
if (isRefresh) {
_articles = articleBeanEntity.data.datas;
} else {
_articles.addAll(articleBeanEntity.data.datas);
} ///接口调用成功后更新数据需要调用setState()方法
setState(() { }); if (articleBeanEntity.data.datas.length ==0) {
//如果接口没有数据返回
if (isRefresh) {
//如果是下拉刷新的时候并且接口没有返回数据,隐藏列表控件,展示空页面
refreshController.refreshFailed();
} else {
//如果是上啦加载更多并且没有返回数据,就展示列表控件,但是下拉提示没有更多数据了
refreshController.loadNoData();
}
} else {
//如果有数据返回,展示列表控件
if (isRefresh) {
//如果是下拉刷新,并且有数据返回正常展示页面数据
refreshController.refreshCompleted();
} else {
//如果是上啦加载,并且有数据返回正常展示页面数据
refreshController.loadComplete();
}
}
}).catchError((onError) {
if (isRefresh) {
//如果下拉刷新,并且接口出错,展示错误页面
refreshController.refreshFailed();
} else {
//如果上拉加载更多,并且接口出错,展示列表控件,底部下拉位置展示加载失败
refreshController.loadFailed();
}
});
} @override
Widget build(BuildContext context) {
return
SmartRefresher(
controller: refreshController,
enablePullUp: true,
onRefresh: onRefresh,
onLoading: loadMore,
header: WaterDropHeader(),
footer: ClassicFooter(),
child:
ListView.builder(
itemBuilder: (context, index) => ItemPage(_articles[index]),
itemCount: _articles.length)
);
}
}

因为要实现的列表支持筛选项,所以我们这里要在构造方法中接收一个cid参数,用来进行列表筛选的,代码很简单,主要是定义来一个下拉刷新和上拉加载更多要执行的方法,然后在接口返回中针对返回的数据处理来对应的刷新状态,以及对异常的处理,注释已经写的很清楚来。

接下来我们新建一个页面,

 @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("文章列表")),
endDrawer: drawerSystem(),
body:ArticleListBaseWidget(key:key,cid: cid));
}

这里endDrawer方法是用来添加一个左滑菜单栏的,这里我们用来显示需要筛选的分类数据组件drawerSystem,该组件是由两个联动的列表组成的,同时在构造方法中,传人两个列表的点击时间,方便调用该组件的页面进行数据更新。这里要注意的是获取状态栏的高度和appbar的高度,还有我们要在endDrawer中自定义一个标题栏,但是endDrawer页面默认会有一个距离顶部的空白高度,我们要利用MediaQuery.removePadding方法来去掉顶部留白的部分,然后设置自己定义的标题栏。这里的appbar高度用常量kToolbarHeight来获取,MediaQuery.of(context).padding.top就是状态栏的高度,看到往上很多是直接写死,这样在不同的机型上面展示的效果会不一样的。

具体代码:

 Widget drawerSystem() {
return MediaQuery.removePadding(
context: context,
removeTop: true,
child: Container(
color: Colors.blue,
width: 320,
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
child: Text("体系数据"),
height: kToolbarHeight + MediaQuery.of(context).padding.top,
//appbar高度+状态栏高度
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top),
alignment: Alignment.center,
color: Colors.grey[200]),
Expanded(
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Container(
child: ListView.separated(
separatorBuilder: (context, index) {
return Divider(
height: 1, color: Colors.grey[50]);
},
itemBuilder: (context, index) => ItemPageSystem(
screenList[index],
null,
index,
(index) => {onItemClick(index)}),
itemCount: screenList.length),
color: Colors.white)),
Expanded(
child: Container(
child: ListView.separated(
separatorBuilder: (context, index) {
return Divider(
height: 1, color: Colors.white);
},
itemBuilder: (context, index) => ItemPageSystem(
null,
screenChildList[index],
index,
(index) => onItemClickChild(index)),
itemCount: screenChildList.length),
color: Colors.grey[50]))
],
))
],
)));
}

ItemPageSystem是listView每该item的样式,可以自己定义,这里要注意的一下,就是listview item的点击事件,这里为来方便在父组件进行数据的处理,所以是从item组件的构造方法将方法传进去的,

 ItemPageSystem(
this.screenDataBean, this.screenChild, this.index, this.function);

然后就可以在点击事件处理筛选的联动效果了,

 //一级筛选点击事件处理
onItemClick(int index) {
setState(() {
//全局记住点击位置
this.index = index;
//设置二级菜单数据集合
screenChildList = screenList[index].children;
//遍历一级数据设置一级菜单标示,是否选中
updateListSelect(index, screenList);
});
} //二级筛选事件处理
onItemClickChild(int index) {
setState(() {
//全局记住二级菜单点击位置
indexChild = index;
//双层循环遍历清空二级菜单为非选中状态
for (int i = 0; i < screenList.length; i++) {
updateListSelect(-1, screenList[i].children);
}
//设置当前点击数据为选中状态
updateListSelect(index, screenChildList);
cid = screenChildList[index].id;
Navigator.pop(context);//关闭侧边菜单栏
key.currentState.refreshController.requestRefresh();
});
}

到这一步基本已经完成了,我们看下效果发现,点击了筛选后并不能更新列表数据,这是为什么呢,查找了半天不知道问题处在哪里,通过查阅文档发现,如果想在父组件里面更新继承自StatefulWidget的组件的数据,光设置setStat还是不行,因为组件的Key是相同的没有改变,所以要想在父组件更新StatefulWidget组件的数据,需要用到GlobalKey,GlobalKey 能够跨 Widget 访问状态,简单来说就是可以通过GlobalKey来调用子组件的方法或者属性。

具体用法:

//在子组件的构造方法中添加一个Key参数。并且调用super方法返回
ArticleListBaseWidget({Key key,this.cid}):super(key:key); //在父组件中初始化组件,ArticleListBaseState为你要更改状态的子组件
final GlobalKey<ArticleListBaseState> key = GlobalKey<ArticleListBaseState>(); //在父组件中初始化子组件的位置,将GlobalKey对象传回到子组件
ArticleListBaseWidget(key:key,cid: cid)); //父组件中,在你需要更新子组件的位置利用GlobalKey对象调用子组件的方法
key.currentState.refreshController.requestRefresh();

在此运行发现,可以通过筛选条件来更新列表了。

Flutter学习六之实现一个带筛选的列表页面的更多相关文章

  1. Flutter学习四之实现一个支持刷新加载的列表

    上一篇文章用Scaffold widget搭建了一个带底部导航栏的的项目架构,这篇文章就来介绍一下在flutter中怎么实现一个带下拉刷新和上拉加载更多的一个列表,这里用到了pull_to_refre ...

  2. Unity3D学习笔记2——绘制一个带纹理的面

    目录 1. 概述 2. 详论 2.1. 网格(Mesh) 2.1.1. 顶点 2.1.2. 顶点索引 2.2. 材质(Material) 2.2.1. 创建材质 2.2.2. 使用材质 2.3. 光照 ...

  3. 「六」创建一个带 weblogic 服务的基础镜像

    Weblogic Weblogic 简单介绍以及其在 Docker 环境下的特殊应用 WebLogic是美国Oracle公司出品的一个application server确切的说是一个基于JAVAEE ...

  4. Flutter学习三之搭建一个简单的项目框架

    上一篇文章介绍了Dart的语法的基本使用,从这篇文章开始,开发一个基于玩Android网站的app.使用的他们开放的api来获取网站数据. 根据网站的结构,我们app最外层框架需要添加一个底部导航栏, ...

  5. 学习ASP.NET Core Blazor编程系列五——列表页面

    学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应用程序(上) 学习ASP.NET Core Blazor编程系 ...

  6. Flutter学习之路---------第一个Flutter项目

    Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面. Flutter可以与现有的代码一起工作.在全世界,Flutter正在被越来越多的开发者和组织使用,并且 ...

  7. 学习ASP.NET MVC(七)——我的第一个ASP.NET MVC 查询页面

    在本篇文章中,我将添加一个新的查询页面(SearchIndex),可以按书籍的种类或名称来进行查询.这个新页面的网址是http://localhost:36878/Book/ SearchIndex. ...

  8. 【Flutter学习】页面布局之基础布局组件

    一,概述 Flutter中拥有30多种预定义的布局widget,常用的有Container.Padding.Center.Flex.Row.Colum.ListView.GridView.按照< ...

  9. 【Flutter学习】基本组件之图片组件Image

    一,概述 Image(图片组件)是显示图像的组件,一个显示图片的widget,支持图像格式:JPEG,PNG,GIF,动画GIF,WebP,动画WebP,BMP和WBMP. Image组件有多种构造函 ...

随机推荐

  1. springboot 读取resources下的文件然后下载

    记录下代码 /** * 下载模板 * * @param response * @param request */ @RequestMapping(value = "downloadTemp& ...

  2. 操作系统-进程(3)Linux下的进程相关命令

    操作系统给予这个内存中的单元一个标识符(PID)依据登入者的UID/GID(/etc/passwd) 衍生出的其它程序(子程序),一般情况也,也会沿用这个程序(父程序)的相关权限 ParentID(P ...

  3. 《Java从入门到失业》第三章:基础语法及基本程序结构(四):基本数据类型(字符编码和char型)

    3.6.4字符编码 咦?怎么好像有东西乱入了?不是讲基本数据类型么?哈哈,因为还剩下最后一个char型了,因为char型会牵涉到Unicode编码相关,因此我决定先科普一下字符集编码. 我儿子现在上小 ...

  4. javascript 数据结构与算法---二叉数

    二叉树,首先了解一些关于二叉数的概念(来自百度百科) 1. 二叉树(Binary tree)是树形结构的一个重要类型 2. 定义: 二叉树(binary tree)是指树中节点的度不大于2的有序树,它 ...

  5. google protocol buffer——protobuf的编码原理二

    这一系列文章主要是对protocol buffer这种编码格式的使用方式.特点.使用技巧进行说明,并在原生protobuf的基础上进行扩展和优化,使得它能更好地为我们服务. 在上一篇文章中,我们主要通 ...

  6. 23种设计模式 - 组件协作(TemplateMethod - Observer/Event - Strategy)

    其他设计模式 23种设计模式(C++) 每一种都有对应理解的相关代码示例 → Git原码 ⌨ 组件协作 现代软件专业分工之后的第一个结果是"框架与应用程序的划分","组件 ...

  7. Update LateUpdae FixedUpdate

    这个问题本来是在研究动画系统时遇到的:OnAnimatorMove在Animator.Update()调用,那这个Animator.Update是什么时候调用的呢. Animator Componen ...

  8. Left Mouse Button (bfs)

    Mine sweeper is a very popular small game in Windows operating system. The object of the game is to ...

  9. Fabric1.4 kafka共识的多orderer集群

    https://www.cnblogs.com/zhangmingcheng/p/10556469.html#FeedBack https://yq.aliyun.com/articles/63746 ...

  10. asp.net中 使用Nginx 配置 IIS站点负载均衡

    这是一偏初学者入门的内容,发现有问题的地方,欢迎留言,一起学习,一起进步 本文主要记录一下在Windows平台中,IIS站点如何使用Nginx 做一个简单的负载均衡  一. 准备工作: 官网下载安装包 ...