如需转载,请注明出处: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实现上拉刷新下拉加载的更多相关文章

  1. ListView上拉刷新和分页加载完整的Dome

    很多人工作的过程中都会碰到ListView下拉刷新和分页加载,然后大多数公司都已经把框架写好了,大家直接用就可以了,有些人一直对这个事情处于迷茫状态,为了让大家对上拉刷新和分页加载有一个比较全面的认识 ...

  2. Android之 RecyclerView,CardView 详解和相对应的上拉刷新下拉加载

    随着 Google 推出了全新的设计语言 Material Design,还迎来了新的 Android 支持库 v7,其中就包含了 Material Design 设计语言中关于 Card 卡片概念的 ...

  3. jQuery模拟原生态App上拉刷新下拉加载

    jQuery模拟原生态App上拉刷新下拉加载效果代码,鼠标上拉时会显示loading字样,并且会模拟加载一条静态数据,支持触屏设备使用. <!doctype html> <html ...

  4. 微信小程序 上拉刷新/下拉加载

    小程序项目中上拉刷新下拉加载是比较常见的需求,官方文档也提供了相当友好的API,但是因为API隐藏的比较深,文档描述也比较模糊所以也折腾了一番(官方文档),在此记录一下使用方式 onPullDownR ...

  5. jQuery WeUI 组件下拉刷新和滚动加载的实现

    最近在做手机版使用到了下拉刷新和滚动加载,记录一下实现过程: 一.引入文件 ? 1 2 3 4 <link rel="stylesheet" href="Conte ...

  6. 实现app上对csdn的文章列表上拉刷新下拉加载以及加入缓存文章列表的功能 (制作csdn app 四)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23698511 今天继续对我们的csdn客户端未完成的功能进行实现,本篇博客接着客 ...

  7. XRecyclerView上拉刷新下拉加载

    效果图: 首先要添加依赖: //xrecyclerviewimplementation 'com.jcodecraeer:xrecyclerview:1.3.2'//Gsonimplementatio ...

  8. iOS:延迟加载和上拉刷新/下拉加载的实现

    lazy懒加载(延迟加载)UITableView 举个例子,当我们在用网易新闻App时,看着那么多的新闻,并不是所有的都是我们感兴趣的,有的时候我们只是很快的滑过,想要快速的略过不喜欢的内容,但是只要 ...

  9. listView上拉刷新下拉加载

    xlistview_header.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLa ...

随机推荐

  1. 【转】DataTable 中数据筛选

    转自:http://blog.163.com/yangxw_2009/blog/static/155255217201032931755646/ 对DataTable进行过滤筛选的一些方法Select ...

  2. Openstack中用keypair生成和访问虚机的方法

    Openstack中用keypair生成和访问虚机的方法 标签:task   iso   perm   cte   生成   复制   vol   rsa   sla Openstack中用镜像文件生 ...

  3. 没事别想不开做Halcon视觉工程师 halcon机器视觉如何学习?

    今天我们来听听看来自一个机器视觉工程师的唠叨和吐槽,在这之后,你还想学人工智能,还想学机器视觉?恭喜你,你对人工智能机器视觉是真爱了! 既然自己选择了这条路,那么无论前进路上有多坎坷,跪着也要走完. ...

  4. containsObject 总是不含有,你会用吗

    结论:containsObject:是在比较内存地址,即使两个对象内容完全一样,地址不同,那也是不同的.我个人认为这个方法应该叫是否存在同一个对象 (开始不知道这个知识,被坑,至少浪费了3个钟头,数组 ...

  5. context创建过程解析(二)之deployWARs

    HostConfig.deployApps() //在监听到start事件类型,也就是StandardHost调用startInternal protected void deployApps() { ...

  6. 第三章 基础算法和数据结构高频题 I

    区间类问题 1 Missing Interval public List<String> findMissingRanges(int[] nums, int lower, int uppe ...

  7. python Django编写接口并用Jmeter测试

    一.环境准备 python3.6.7 Pycharm 二.创建项目 我这里是在Django项目中新建了个APP,目录结构如下图所示: 那么怎么在已有的Django项目中新建APP并进行配置呢: 2.1 ...

  8. Vue中动态(import 、require)显示img图片

    vue中,经常会遇到显示图片的问题, 如果是一个普通组件的话,那么这样就可以了 <img src="../assets/images/avtor.jpg" width=&qu ...

  9. 干货来了!python学习之重难点整理合辑1

    关于装饰器.lambda.鸭子类型.魔法函数的理解仍存有困惑之处,趁周末有时间温故,赶紧去自学了解下相关知识. 1.装饰器是什么: 很多初学者在接触装饰器的时候只做到了肤浅的了解它的概念.组成形态.实 ...

  10. spring boot 加载自定义log4j 文件路径

    spring boot 使用log4j 打印时,需首先去除自带 Logger ,然后加入log4j 依赖 <dependencies> <!-- https://mvnreposit ...