Hello 大家好,最近在 flutter 中用到了列表展示数据,并且实现了上拉加载和下拉刷新,当时就想如何把他们抽象出来,形成一个 widget ,于是就有了下面这篇文章。
先看下效果图
请忽略填充的内容[允悲]
具体实现
下拉刷新使用的是:RefreshIndicator,上拉加载是用的 ScrollController 的监听。代码如下:
import 'package:flutter/material.dart';
// ignore: must_be_immutable
class RecycleView<T> extends StatefulWidget {
Function loadMore;
Function refresh;
List<T> lists;
Function listBuilder;
RecycleView(
{Key key,
@required this.lists,
this.loadMore,
this.refresh,
this.listBuilder})
: super(key: key);
@override
State<StatefulWidget> createState() => _Recycle();
}
class _Recycle extends State<RecycleView> {
//下拉刷新触发距离
static const double DISPLACEMENT = 40.0;
//是否显示正在加载
bool _showLoading = false;
ScrollController _scrollController = ScrollController();
@override
void didUpdateWidget(RecycleView oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.lists == widget.lists && oldWidget.lists.isNotEmpty) {
_showLoading = false;
}
}
@override
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
if (!_showLoading && widget.lists.isNotEmpty) {
setState(() {
_showLoading = true;
});
_loadMore();
}
}
});
}
_refresh() {
if (widget.refresh != null) {
widget.refresh();
setState(() {
_showLoading = false;
});
}
}
_loadMore() {
if (widget.loadMore != null) {
widget.loadMore();
}
setState(() {});
}
@override
Widget build(BuildContext context) {
if (widget.lists == null || widget.lists.isEmpty) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: CircularProgressIndicator(),
),
);
} else {
return RefreshIndicator(
onRefresh: () async {
await _refresh();
},
displacement: DISPLACEMENT,
child: ListView.builder(
itemCount: widget.lists.length + 1,
itemBuilder: (context, index) {
if (index == widget.lists.length) {
return _showLoading ? _loadingWidget() : _noMoreWidget();
} else {
return widget.listBuilder(context, index);
//return Text("3333$index");
}
},
controller: _scrollController,
),
);
}
}
Widget _loadingWidget() {
return Offstage(
offstage: false,
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new CircularProgressIndicator(),
),
));
}
Widget _noMoreWidget() {
return Offstage(
offstage: false,
child: Center(
child: Container(
padding: EdgeInsets.only(top: 5, bottom: 5),
child: Text("没有更多啦~"))));
}
}
ok ,这样就大体完成了。这里只起个抛砖引玉的作用,希望能给你提供些思路。
新增了itemCount属性,帮助自由构建子项,代码修改部分如下:
这样只需要传入不同的itemCount即可构建任意的子项了,如在以上的效果下新增轮播图。
return Scaffold(
body: RecycleView<HomeArticleEntity>(
lists: lists,
loadMore: () {
_loadData(++_currentPage);
},
refresh: () {
_currentPage = _initPageCount;
_loadData(_currentPage);
},
//这里定义了子项大小
itemCount: lists.length + 1,
listBuilder: _createBuilder,
),
);
Widget _createBuilder(BuildContext context, int index) {
if (index == 0) {
return Container(
height: 200,
color: Colors.red,
);
} else {
return xxxx;
}
}
最终效果如下:
可以看到多了一个高度200dp的红色contener。