Flutter学习笔记(25)--ListView实现上拉刷新下拉加载
如需转载,请注明出处:Flutter学习笔记(25)--ListView实现上拉刷新下拉加载
前面我们有写过ListView的使用:Flutter学习笔记(12)--列表组件,当列表的数据非常多时,需要使用长列表,比如淘宝后台的订单列表,手机通讯录等,这些列表项数据很多,长列表也是使用ListView作为基础组件,只不过需要添加一个列表项构造器itemBuilder。Flutter的长列表组件其实相当于Android中的RecyclerView,它会自动为您回收列表元素。在创建ListView.builder时,需要传入两个参数,一个列表的初始长度,一个itemBuilder函数。ListVIew还支持基于Sliver的延迟构建模型。
基于Sliver的延迟构建模式:
通常可滚动组件的子组件可能会非常多,占用的总高度也会非常大,如果要一次性将子组件全部构建出将会导致性能差的问题出现,为此,Flutter中提出一个Sliver(中文为"薄片"的意思)概念,如果一个可滚动组件支持Sliver模型,那么该滚动组件可以将子组件分成好多个薄片(Sliver),只有当Sliver出现在视口时才会去构建它,这种模型也成为"基于Sliver的延迟构建模型"。可滚动组件中有很多都支持基于Sliver的延迟构建模型,如ListView、GridView,但是也有不支持该模型的,如SingleChildScrollView
使用ListVIew.separated给列表项之间添加一个分割组件
import 'package:flutter/material.dart';
void main() => runApp(DemoApp());
class DemoApp extends StatelessWidget {
//初始化数据源
final List<String> items = new List<String>.generate(, (i)=>"Item $i");
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'SingleChildScrollView Demo',
home: new Scaffold(
appBar: AppBar(
title: new Text('SingleChildScrollView Demo'),
),
body:new ListView.separated(
//列表滑动到边界时,显示iOS的弹出效果
physics: BouncingScrollPhysics(),
itemCount: items.length,
//列表项构造器
itemBuilder: (context,index){
return ListTile(title: new Text('${items[index]}'),);
},
//分割构造器
separatorBuilder: (context,index){
//分割组件
return new Divider(color: Colors.blue,);
},
),
),
);
}
}

下拉刷新
Flutter给我们提供了下拉刷新功能RefreshIndicator的组件,先整体说明一下下面Demo的代码逻辑,其实很简单,body返回一个RefreshIndicator组件,在该组件内的子组件是一个ListView,重点说一下RefreshIndicator的下拉回调方法onRefresh,在回调方法内延迟2秒中后将list内容清空,并且重新给list列表添加新的数据。
import 'package:flutter/material.dart';
void main() => runApp(DemoApp());
class DemoApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _DemoAppState();
}
}
class _DemoAppState extends State<DemoApp> {
var _items = new List<String>();
@override
void initState() {
super.initState();
getData();
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'ListView Demo',
home: new Scaffold(
appBar: new AppBar(
title: new Text('ListView Demo'),
),
body: new RefreshIndicator(
onRefresh: _onRefresh,
child: new ListView.separated(
physics: BouncingScrollPhysics(),
itemBuilder: (context,index){
return ListTile(title:new Text('${_items[index]}'));
},
//分割线构造器
separatorBuilder: (context,index){
return new Divider(color: Colors.blue,);
},
//_items.length + 1是为了给最后一行的加载loading留出位置
itemCount: _items.length
),
),
),
);
}
void getData() {
//初始数据源
for (int i=;i<;i++){
_items.insert(_items.length, "第${_items.length}条原始数据");
print(_items[i]);
}
}
Future<void> _onRefresh() async {
await Future.delayed(Duration(seconds: )).then((e){
setState(() {
_items.clear();
for (int i=;i<;i++){
_items.insert(_items.length, "第${_items.length}条下拉刷新后的数据");
}
});
});
}
@override
void dispose() {
super.dispose();
}
}
这里需要注意的是,onRefresh回调方法要增加async....await,不然会出现下拉刷新的loading不会消失的问题:
Future<void> _onRefresh() async {
await Future.delayed(Duration(seconds: )).then((e){
setState(() {
_items.clear();
for (int i=;i<;i++){
_items.insert(_items.length, "第${_items.length}条下拉刷新后的数据");
}
});
});
}

上拉加载
先缕一下实现的思路,我们想要实现的效果是每页20条内容,共5页的内容,1-4页末尾数据后要展示加载新数据的loading,到第5页末尾数据展示“我是有底线的”,因此,我们的itemCount就要是itemCount: _items.length + 1.而不是itemCount: _items.length + ,这是因为要在最后留出来loading的位置,接下来就是要处理构建LisvtView里面的每一条item,如果当前item的索引是列表数据的最后一条数据,并且不是最后一页的话,展示loading,如果当前item的索引是列表数据的最后一条数据,并且是最后一页的话,展示“我是有底线的”,如果当前item的索引不是列表数据的最后一条,则展示下一条数据的内容。最后要处理的就是当页面滑动到最后了,要怎么获取新的数据。前面我们在写页面滑动的部分有讲到过controller属性(此属性接收一个ScrollController对象,ScrollController的主要作用是控制滚动位置和监听滚动事件),我们现在需要做的就是通过ListView的controller控制器来判断页面是否滑动到了最底部,如果滑动到了最底部,则获取新的数据并插入到list里面,最后通过setState通知页面重新构建。
import 'package:flutter/material.dart';
void main() => runApp(DemoApp());
class DemoApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new _DemoAppState();
}
}
class _DemoAppState extends State<DemoApp> {
ScrollController _controller = new ScrollController();
var _items = new List<String>();
var _mPage = ;
@override
void initState() {
super.initState();
getData();
//给_controller添加监听
_controller.addListener((){
//判断是否滑动到了页面的最底部
if(_controller.position.pixels == _controller.position.maxScrollExtent){
//如果不是最后一页数据,则生成新的数据添加到list里面
if(_mPage < ){
_retrieveData();
}
}
});
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'ListView Demo',
home: new Scaffold(
appBar: new AppBar(
title: new Text('ListView Demo'),
),
body: new RefreshIndicator(
onRefresh: _onRefresh,
child: new ListView.separated(
controller: _controller,
physics: BouncingScrollPhysics(),
itemBuilder: (context,index){
//判断是否构建到了最后一条item
if(index == _items.length){
//判断是不是最后一页
if(_mPage < ){
//不是最后一页,返回一个loading窗
return new Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.center,
child: SizedBox(
width: 24.0,
height: 24.0,
child: CircularProgressIndicator(strokeWidth: 2.0,),
),
);
}else{
//是最后一页,显示我是有底线的
return new Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.center,
child: new Text('我是有底线的!!!',style:TextStyle(color: Colors.blue),),
);
}
}else{
return ListTile(title:new Text('${_items[index]}'));
}
},
//分割线构造器
separatorBuilder: (context,index){
return new Divider(color: Colors.blue,);
},
//_items.length + 1是为了给最后一行的加载loading留出位置
itemCount: _items.length +
),
),
),
);
}
void getData() {
//初始数据源
for (int i=;i<;i++){
_items.insert(_items.length, "第${_items.length}条原始数据");
print(_items[i]);
}
}
void _retrieveData() {
//上拉加载新的数据
_mPage++;
Future.delayed(Duration(seconds: )).then((e){
for (int i=;i<;i++){
_items.insert(_items.length, "这是新加载的第${_items.length}条数据");
}
setState(() {
});
});
}
Future<void> _onRefresh() async {
await Future.delayed(Duration(seconds: )).then((e){
setState(() {
_mPage = ;
_items.clear();
for (int i=;i<;i++){
_items.insert(_items.length, "第${_items.length}条下拉刷新后的数据");
}
});
});
}
@override
void dispose() {
//移除监听,防止内存泄漏
_controller.dispose();
super.dispose();
}
}

以上就是今天下拉刷新和上拉加载的全部内容了,如果有错误的地方或者有任何疑问,欢迎留言!!!
Flutter学习笔记(25)--ListView实现上拉刷新下拉加载的更多相关文章
- ListView上拉刷新和分页加载完整的Dome
很多人工作的过程中都会碰到ListView下拉刷新和分页加载,然后大多数公司都已经把框架写好了,大家直接用就可以了,有些人一直对这个事情处于迷茫状态,为了让大家对上拉刷新和分页加载有一个比较全面的认识 ...
- Android之 RecyclerView,CardView 详解和相对应的上拉刷新下拉加载
随着 Google 推出了全新的设计语言 Material Design,还迎来了新的 Android 支持库 v7,其中就包含了 Material Design 设计语言中关于 Card 卡片概念的 ...
- jQuery模拟原生态App上拉刷新下拉加载
jQuery模拟原生态App上拉刷新下拉加载效果代码,鼠标上拉时会显示loading字样,并且会模拟加载一条静态数据,支持触屏设备使用. <!doctype html> <html ...
- 微信小程序 上拉刷新/下拉加载
小程序项目中上拉刷新下拉加载是比较常见的需求,官方文档也提供了相当友好的API,但是因为API隐藏的比较深,文档描述也比较模糊所以也折腾了一番(官方文档),在此记录一下使用方式 onPullDownR ...
- jQuery WeUI 组件下拉刷新和滚动加载的实现
最近在做手机版使用到了下拉刷新和滚动加载,记录一下实现过程: 一.引入文件 ? 1 2 3 4 <link rel="stylesheet" href="Conte ...
- 实现app上对csdn的文章列表上拉刷新下拉加载以及加入缓存文章列表的功能 (制作csdn app 四)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23698511 今天继续对我们的csdn客户端未完成的功能进行实现,本篇博客接着客 ...
- XRecyclerView上拉刷新下拉加载
效果图: 首先要添加依赖: //xrecyclerviewimplementation 'com.jcodecraeer:xrecyclerview:1.3.2'//Gsonimplementatio ...
- iOS:延迟加载和上拉刷新/下拉加载的实现
lazy懒加载(延迟加载)UITableView 举个例子,当我们在用网易新闻App时,看着那么多的新闻,并不是所有的都是我们感兴趣的,有的时候我们只是很快的滑过,想要快速的略过不喜欢的内容,但是只要 ...
- listView上拉刷新下拉加载
xlistview_header.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLa ...
随机推荐
- Winform 连接Web Service 记录
一般自己控制的项目都会使用webApi,比较少使用WS,感觉要配置一堆东西很繁琐. 场景:多个系统间数据交互. 角色:我们属于下游系统,要把一部分数据格式化后上传到SAP中. SAP提供了一个WS,使 ...
- maven install时跳过测试
xl_echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! - ...
- C#命名规范(简述)
命名空间,类,事件,接口,常量,属性,方法使用Pascal命名,即首字母大写 参数,变量(类字段)使用camel命名法,即首字母小写. Pascal 方式--所有单词第一个字母大写,其他字母小写. ...
- PHP强制转换类型
PHP强制转换类型 获取数据类型 : 1.如果想查看某个表达式的值和类型,用var_dump(). 2.如果只是想得到一个易读懂的类型的表达方式用于调试,用 gettype().3.要查看某个类型 ...
- java练习---6
//程序员:罗元昊 2017.9.24 import java.util.Scanner; public class L { public static void main(String[] args ...
- 10w数组去重,排序,找最多出现次数
配置在博客底部 主函数 package ooDay11.zy13; import ooDay11.zy13.hanshu.GetKeyList;import ooDay11.zy13.hanshu.G ...
- 【MySQL】Unknown column 'column_name' in 'field list'
使用 INSERT INTO - SELECT FROM - ON DUPLICATE KEY UPDATE 时遇到了这个问题,百思不得其解
- div 环形排列
javascript-按圆形排列DIV元素(一)---- 分析 效果图: 一.分析图: 绿色边框内:外层的DIV元素,相对定位; 白色圆形框:辅助分析的想象形状; 白点:为白色圆形的圆心点,中心点,点 ...
- Go中的fmt几种输出的区别和格式化方式
在日常使用fmt包的过程中,各种眼花缭乱的print是否让你莫名的不知所措呢,更让你茫然的是各种格式化的占位符..简直就是噩梦.今天就让我们来征服格式化输出,做一个会输出的Goer. fmt.Prin ...
- JAVA MQ API方式通信采用Binding MQ Server方式
package com.mqapi; /** * @modified by actorai E-mail:actorai@163.com * @version 创建时间:2010-9-15 * ...