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 ...
随机推荐
- vue-cli - webpack 打包兼容 360 浏览器和 IE 浏览器
index.html增加一行代码 <head> <meta charset="utf-8"> <meta name="viewport&qu ...
- lr参数化
为什么做参数化? 数据库校验:注册用户时会看数据库有没有这个账号 应用程序校验:pc端qq登陆,一个账号只能登陆一台电脑 1.数据库或应用程序提交值的唯一性校验 数据库查询过程: 1.语法检查.语义检 ...
- jango简介
Django简介 Django框架简介 MVC框架和MTV框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Mode ...
- cookbook_模块和包
1把模块按层次结构组织成包 只需确保每个目录中都定义了__init__.py即可. 2对所有符号的导入进行精确控制 当用户使用from module import * 语句时,我们希望对从模块或包中导 ...
- bean的创建(五)第一部分
AbstractBeanFactory.doGetBean protected <T> T doGetBean( final String name, final Class<T&g ...
- zabbix监控WEB网站性能
一直在纠结用什么实例来给大家演示呢?想来想去还是官方的好,那我们怎么用zabbix监控web性能和可用性呢?我们这边分为几个步骤:打开网站.登陆.登陆验证.退出,一共4个小step,看实例. 检测流程 ...
- html+css+dom补充
补充1:页面布局 一般像京东主页左侧右侧都留有空白,用margin:0 auto居中,一般.w. <!DOCTYPE html> <html lang="en"& ...
- 15分钟让你了解如何实现并发中的Barrier
说到Barrier,很多语言中已经是标准库中自带的概念,一般情况下,只需要直接使用就行了.而最近一些机缘巧合的机会,我需要在c++中使用这么个玩意儿.但是c++标准库里还没有这个概念,只有boost里 ...
- js 双向绑定数据
let aaa = []; let bbb = [1,2,3]; let ccc = [0,9,8]; aaa = bbb; //此时aaa与bbb被绑定(aaa指向bbb的指向) ,若使用push则 ...
- MVP架构下解决 RxJava 自动解绑问题
背景 MVP 模式下使用 RxJava 处理网络访问的回调,当数据返回时 Presenter 调用绑定的 View 的方法. 定义 BasePresenter 如下: public class Bas ...