在Flutter开发之ListView下拉刷新&上拉加载更多(35) 中我们实现了下拉刷新、上拉分页加载的功能。但是使用起来非常不方便,且不满一屏时难以处理。
今天介绍ListView使用第三方pull_to_refresh
来实现下拉刷新、上拉分页加载。
pull_to_refresh
依赖官方文档:https://pub.dev/packages/pull_to_refresh#-installing-tab-
我们可以通过pubspec.yaml文件引入最新版本
dependencies:
pull_to_refresh: ^1.5.0
import 'package:pull_to_refresh/pull_to_refresh.dart';
使用示例
https://pub.dev/packages/pull_to_refresh#-readme-tab-
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:flutter/cupertino.dart';
class ListViewPulltoRefresh extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('ListViewPulltoRefresh'),
),
body: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
List items = ["1", "2", "3", "4", "5"];
// List items = ["1", "2", "3", "4", "5", "6", "7", "8"];
RefreshController _refreshController =
RefreshController(initialRefresh: true);
void _onRefresh() async {
// monitor network fetch
await Future.delayed(Duration(milliseconds: 1000));
// if failed,use refreshFailed()
_refreshController.refreshCompleted();
}
void _onLoading() async {
// monitor network fetch
await Future.delayed(Duration(milliseconds: 1000));
// if failed,use loadFailed(),if no data return,use LoadNodata()
items.add((items.length + 1).toString());
if (mounted)
setState(() {
});
_refreshController.loadComplete();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SmartRefresher(
enablePullDown: true,
enablePullUp: true,
// WaterDropHeader、ClassicHeader、CustomHeader、LinkHeader、MaterialClassicHeader、WaterDropMaterialHeader
header: ClassicHeader(
// height: 45.0,
// releaseText: '松开手刷新',
// refreshingText: '刷新中',
// completeText: '刷新完成',
// failedText: '刷新失败',
// idleText: '下拉刷新',
),
// ClassicFooter、CustomFooter、LinkFooter、LoadIndicator
footer: CustomFooter(
builder: (BuildContext context, LoadStatus mode) {
Widget body;
if (mode == LoadStatus.idle) {
body = Text("pull up load");
}
else if (mode == LoadStatus.loading) {
body = CupertinoActivityIndicator();
}
else if (mode == LoadStatus.failed) {
body = Text("Load Failed!Click retry!");
}
else {
body = Text("No more Data");
}
return Container(
height: 55.0,
child: Center(child: body),
);
},
),
controller: _refreshController,
onRefresh: _onRefresh,
onLoading: _onLoading,
child: ListView.builder(
itemBuilder: (c, i) => Card(child: Center(child: Text(items[i]))),
itemExtent: 100.0,
itemCount: items.length,
),
),
);
}
// don't forget to dispose refreshController
@override
void dispose() {
// TODO: implement dispose
_refreshController.dispose();
super.dispose();
}
}
代码中分别使用了小于一屏幕的数据和10条数据测验,以及header: footer: 的自定义样式选择的使用。实际效果根据需要选择不同的参数。更多使用请看:
https://pub.dev/packages/pull_to_refresh#-readme-tab-
头部吸顶,滑动收起背景效果。
增加代码_headerView(),将body处改为body:_headerView(),
// 顶部有背景的效果
Widget _headerView(){
return new CustomScrollView(
physics: new BouncingScrollPhysics(),
// 需要使用 slivers 才可以
slivers: [
// 头部内容
new SliverAppBar(
// 高度
expandedHeight: 256.0,
pinned: true,
floating: !true,
snap: !true,
flexibleSpace: new FlexibleSpaceBar(
// 标题
title: Text('标题'),
centerTitle: true,
// 背景图
background: new Image.network(
'http://img.anfone.net/Outside/anfone/201666/2016661523021277.jpg',
fit: BoxFit.cover,
),
),
),
// 列表内容
new SliverList(
delegate: new SliverChildBuilderDelegate((ctx, index) {
return Container(
height: 40,
child: new Text('item: $index'),
);
},
childCount: 50),
),
],
);
}
如下效果: