热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

FlutterListView如何实现上拉加载更多下拉刷新功能

这篇文章给大家分享的是有关FlutterListView如何实现上拉加载更多下拉刷新功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小

这篇文章给大家分享的是有关Flutter ListView如何实现上拉加载更多下拉刷新功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

先上图

Flutter ListView如何实现上拉加载更多下拉刷新功能

下拉刷新

跟原生开发一样,下拉刷新在flutter里提供的有组件实现 RefreshIndicator

一直不明白为啥组件中都提供下拉刷新,但就是没有上拉加载!!

我这请求接口数据用的是 http 库,是个第三方的是需要安装的 https://pub.dev/packages/http

用法如下

class MyHomePage extends StatefulWidget {
 MyHomePage({Key key}) : super(key: key);
 @override
 MyHomeWidget2 createState() => MyHomeWidget2();
}
class MyHomeWidget2 extends State {
 int page = 1;
 List data = new List();
 var baseUrl = "https://cnodejs.org/api/v1";
 @override
 void initState() {
 super.initState();
 this._onRefresh();
 }
 _fetchData() async {
 var response = await http.get(
  '${this.baseUrl}/topics?mdrender=false&limit=10&page=${this.page}');
 var json = await convert.jsonDecode(response.body);
 return json['data'];
 }
 Future _onRefresh() {
 data.clear();
 this.page = 1;
 return _fetchData().then((data) {
  setState(() => this.data.addAll(data));
 });
 }
 @override
 Widget build(BuildContext context) {
 return Scaffold(
  body: RefreshIndicator( // 在ListView外包一层 RefreshIndicator 组件
  onRefresh: _onRefresh, // 添加onRefresh方法
  child: ListView.separated(
   itemCount: this.data.length,
   itemBuilder: (context, index) {
   var _data = this.data[index];
   return ListTile(
    leading: Image.network(_data["author"]["avatar_url"]),
    title: Text(_data["title"]),
    subtitle: Text(_data["author"]["loginname"] +
     " created at " +
     new DateTime.now().toString()), // 为了看每次数据变动,这里直接取当前时间
    trailing: Icon(Icons.chevron_right));
   },
   separatorBuilder: (context, index) {
   return Divider();
   },
  )
 ));
 }
}

链接文原: https://tomoya92.github.io/2019/07/17/flutter-refresh-loadmore/

上拉加载

上拉加载原理还是一样的,给ListView加一个 ScrollController 组件,然后通过事件监听滚动条的高度来显示和隐藏加载更多的组件

先将加载更多的组件写好

Widget _loadMoreWidget() {
 return new Padding(
 padding: const EdgeInsets.all(15.0), // 外边距
 child: new Center(
  child: new CircularProgressIndicator()
 ),
 );
}

初始化一个 ScrollController 组件,将其设置给 ListView 组件的 controller 属性上

ScrollController _scrollController = new ScrollController();

child: ListView.separated(
 controller: _scrollController,
 //...
)

然后通过重写 dispost() 方法来处理加载更多组件的释放

@override
void dispose() {
 _scrollController.dispose();
 super.dispose();
}

最后通过数据源来控制界面渲染哪个组件,当数据源循环渲染的 index 跟数据源一样长时(其实少1,下标从0开始的)就渲染加载更多组件,让其显示出来,同时调用加载更多方法,获取数据,再通过state实现组件ui的更新

完整代码如下

class MyHomePage extends StatefulWidget {
 MyHomePage({Key key}) : super(key: key);
 @override
 MyHomeWidget2 createState() => MyHomeWidget2();
}
class MyHomeWidget2 extends State {
 int page = 1;
 bool isLoadmore = false;
 List data = new List();
 var baseUrl = "https://cnodejs.org/api/v1";
 ScrollController _scrollController = new ScrollController();
 @override
 void initState() {
 super.initState();
 this._onRefresh();
 _scrollController.addListener(() {
  if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
  _onLoadmore();
  }
 });
 }
 _fetchData() async {
 var response = await http.get(
  '${this.baseUrl}/topics?mdrender=false&limit=10&page=${this.page}');
 var json = await convert.jsonDecode(response.body);
 return json['data'];
 }
 Future _onRefresh() {
 data.clear();
 this.page = 1;
 return _fetchData().then((data) {
  setState(() => this.data.addAll(data));
 });
 }
 Future _onLoadmore() {
 this.page++;
 return _fetchData().then((data) {
  setState((){
  this.data.addAll(data);
  isLoadmore = false;
  });
 });
 }
 @override
 void dispose() {
 _scrollController.dispose();
 super.dispose();
 }
 Widget _loadMoreWidget() {
 return new Padding(
  padding: const EdgeInsets.all(15.0),
  child: new Center(
  child: new CircularProgressIndicator()
  ),
 );
 }
 @override
 Widget build(BuildContext context) {
 return Scaffold(
  body: RefreshIndicator(
  onRefresh: _onRefresh,
  child: ListView.separated(
   controller: _scrollController,
   itemCount: this.data.length,
   itemBuilder: (context, index) {
   if (index == data.length - 1) {
    return _loadMoreWidget();
   } else {
    var _data = this.data[index];
    return ListTile(
     leading: Image.network(_data["author"]["avatar_url"]),
     title: Text(_data["title"]),
     subtitle: Text(_data["author"]["loginname"] +
      " created at " +
      new DateTime.now().toString()),
     trailing: Icon(Icons.chevron_right));
   }
   },
   separatorBuilder: (context, index) {
   return Divider();
   },
  )
 ));
 }
}

感谢各位的阅读!关于“Flutter ListView如何实现上拉加载更多下拉刷新功能”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!


推荐阅读
  • 使用Flutternewintegration_test进行示例集成测试?回答首先在dev下的p ... [详细]
  • 今日份分享:Flutter自定义之旋转木马
    今日份分享:Flutter自定义之旋转木马-先上图,带你回到童年时光:效果分析子布局按照圆形顺序放置且平分角度子布局旋转、支持手势滑动旋转、快速滑动抬手继续旋转、自动旋转支持X轴旋 ... [详细]
  • 最近这段时间用了下RestTemplate这个类,抽点时间总结下一些东西,希望对大家有所帮助。从3.0版本开始,Spring提供了RestTemplate作为用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。本篇文章将从RestTemplate提供的API入手,先来了解下RestTemplate的具体使用,然后再对其中涉及 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文是一篇翻译文章,介绍了async/await的用法和特点。async关键字被放置在函数前面,意味着该函数总是返回一个promise。文章还提到了可以显式返回一个promise的方法。该特性使得async/await更易于理解和使用。本文还提到了一些可能的错误,并希望读者能够指正。 ... [详细]
  • 一、路由首先需要配置路由,就是点击good组件进入goodDetail组件配置路由如下{path:goodDetail,component:goodDetail}同时在good组件中写入如下点击事件,路由中加入 ... [详细]
  • STM32 IO口模拟串口通讯
    转自:http:ziye334.blog.163.comblogstatic224306191201452833850647前阵子,调项目时需要用到低波 ... [详细]
  • Flutter 布局(四) Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth详解
    本文主要介绍Flutter布局中的Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth四种控件,详细介绍了其布局 ... [详细]
  • 当我在doWork方法中运行代码时,通过单击button1,进度条按预期工作.但是,当我从其他方法(即btn2,btn3)将列表传递给doWork方法时,进度条在启动后会跳转到10 ... [详细]
  • 图解 Google V8 # 19 :异步编程(二):V8 是如何实现 async/await 的?
    说明图解GoogleV8学习笔记前端异步编程的方案史1、什么是回调地狱?如果在代码中过多地使用异步回调函数,会将整个代码逻辑打乱,从 ... [详细]
author-avatar
海and云
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有