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

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

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

class ArticleListBaseWidget extends StatefulWidget {  int cid = 0; //文章分类的id  @override  StatecreateState() {    return ArticleListBaseState();  }  ArticleListBaseWidget({this.cid});}class ArticleListBaseState extends State<ArticleListBaseWidget> {  RefreshController refreshController =      RefreshController(initialRefresh: true);  int pageNum = 0;  List _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: [                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: [                    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 key = GlobalKey();   //在父组件中初始化子组件的位置,将GlobalKey对象传回到子组件 ArticleListBaseWidget(key:key,cid: cid));  //父组件中,在你需要更新子组件的位置利用GlobalKey对象调用子组件的方法  key.currentState.refreshController.requestRefresh();

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

android 筛选控件_Flutter学习六之实现一个带筛选的列表页面相关推荐

  1. Android学习--02(猜猜我的星座App源码+Android常用控件TextView+EditText+Button+ImangeView+DatePicker+App间通信+跳转页面)

    猜猜我的星座App 1 Android常用控件 1.1 TextView控件 1.1.1 简介 1.1.2属性 1.1.3 扩展属性 1.1.4 TextView的使用方法 1.1.5总结 1.2 E ...

  2. Android提供了哪些主要UI控件,Android必备:Android UI控件的了解与学习

    因为工做须要,最近一段时间,须要进行Android App开发的学习,以前简单的进行过Android的了解,对于基本的Android环境的搭建等已经有过整理,一个Android App是由一个或多个A ...

  3. Android 开源控件与常用开发框架开发工具类

    Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...

  4. 日历控件的android代码,Android日历控件PickTime代码实例

    Android日历控件PickTime代码实例 发布时间:2020-10-03 16:05:51 来源:脚本之家 阅读:86 作者:手撕高达的村长 最近做项目,需要设置用户的生日,所以做这样一个功能. ...

  5. android控件使用大全,Android常见控件使用详解

    本文实例为大家分享了六种Android常见控件的使用方法,供大家参考,具体内容如下 1.TextView 主要用于界面上显示一段文本信息 2.Button 用于和用户交互的一个按钮控件 //为Butt ...

  6. android组件用法说明,Android第三方控件PhotoView使用方法详解

    Android第三方控件PhotoView使用方法详解 发布时间:2020-10-21 15:06:09 来源:脚本之家 阅读:74 作者:zhaihaohao1 PhotoView的简介: 这是一个 ...

  7. Android神奇“控件”-----RemoteViews

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 转载请注明 http://blog.csdn.net/wrg_20100512/article/details/53940485 好 ...

  8. android 实现控件搜索折叠效果 Animation动画折叠和普通折叠

    android 实现控件搜索折叠效果 Animation动画折叠和普通控件直接折叠效果: 原理很简单,都是获取对应的高度,通过实现高度变化而改变显示效果: 话不多说直接上代码 1.普通折叠效果,以下是 ...

  9. Android 原生控件之一 TextView

    Android 原生控件之一 TextView 前言 来源 开始 XML属性 1.android:allowUndo 2.android:autoLink 3.android:autoSizeMaxT ...

最新文章

  1. R语言ggplot2可视化:将条形图(bar plot)和线图(line plot)组合在一起并使用双Y轴(double y axis)进行可视化、其中一个Y轴显示为百分比
  2. SSL--用Tomcat服务器配置https双向认证过程实战
  3. 一元享移动怎么样_移动大王卡千万别买!!!
  4. qgraphicsview鼠标移动图片_如何在中间鼠标的QGraphicsView中滚动QGraphicsScene?
  5. C#实现树型结构TreeView节点拖拽的简单功能,附全部源码,供有需要的参考
  6. php页面生成html页面显示,把当前显示的动态PHP页面静态化,生成HTML文件
  7. 8月13日见!三星Note 20国行版官宣:唯一悬念只剩价格
  8. STL sort 函数实现详解 ZZ
  9. 使用mybatis-generator自动生成代码(附GitHub下载地址)
  10. 考研数学——求极限方法总结
  11. SQLAlchemy session 使用问题
  12. android 声音不想从蓝牙手机中出来,Android蓝牙音频两个问题
  13. java-php-python-ssm医药网络挂号系统计算机毕业设计
  14. Blos查看计算机硬盘,bios查看硬盘损坏
  15. Python自学教程
  16. Windows环境下安装scrapy
  17. 【Java实验五】字符串加密、模拟用户登录、生成验证码、春节倒计时等
  18. 女人最难挡男人的3种诱惑
  19. 一般网站有哪些类型的
  20. Vue原生图片瀑布流

热门文章

  1. angularjs中state的参数4_mpvue中使用Vuex
  2. 限制python内存上限_Python限制内存和CPU使用量的方法(Unix系统适用)
  3. IDEA万能快捷键,你不知道的17个实用技巧!!!
  4. 线上Bug无法复现怎么办?老司机教你一招,SpringBoot远程调试不用愁!
  5. 解密微信小程序Java登录流程(ssm实现具体功能)
  6. String类为什么是final
  7. postman怎么不登陆使用_钉钉登陆不了怎么办,那时的网速也不流畅,怎么办
  8. 计算营业额的python代码_【每日一练】巧用python实现利润计算
  9. windows 搭建python 虚拟环境 写程序_Windows下搭建Python虚拟环境
  10. Redis之慢查询分析