1. 下拉刷新
Flutter中提供了组件 RefreshIndicator用于下拉刷新。
其基本的实现方法是在该组件添加onRefresh事件,当用户下拉刷新时会触发该事件,在该事件中可以用调用一个延时任务Future.delayed( ),在延时任务的回调中重新请求数据即可。
2. 上拉加载更多
Flutter中主要通过使用 ListView.builder( ) 添加控制器来实现上拉加载更多。
其基本的实现方法是在该组件里添加控制器,在组件初始化时实例化ScrollController类型控制器,然后在初始化的initState( )中,给控制器添加addListener( )监听事件,在事件的回调函数中可以获得滚动的下拉距离及整个页面的高度,然后判断这两个值的相差距离值,其值快接近时触发数据请求。
3. 代码实例
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:dio/dio.dart';
class NewsPage extends StatefulWidget {
NewsPage({Key key}) : super(key: key);
@override
_NewsPageState createState() => _NewsPageState();
}
class _NewsPageState extends State<NewsPage> {
// 当前页数
int _page = 1;
// 页面数据
List _list = [];
// 是否还有
bool _hasMore = true;
// 滚动控制器
ScrollController _scrollController = new ScrollController();
@override
void initState() {
super.initState();
this._getData();
// 监听滚动事件
_scrollController.addListener((){
// 获取滚动条下拉的距离
// print(_scrollController.position.pixels);
// 获取整个页面的高度
// print(_scrollController.position.maxScrollExtent);
if(_scrollController.position.pixels>_scrollController.position.maxScrollExtent-40){
this._getData();
}
});
}
// 获取数据列表
void _getData() async{
if(this._hasMore){
var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=${_page}";
Response result = await Dio().get(url);
var list = json.decode(result.data)["result"];
setState(() {
// 拼接数据
this._list.addAll(list);
// 页数累加
this._page++;
});
if(list.length<20){
setState(() {
// 关闭加载
this._hasMore = false;
});
}
}
}
// 下拉刷新
Future<void> _onRefresh() async{
print("下拉刷新");
// 持续两秒
await Future.delayed(Duration(milliseconds:2000),(){
this._getData();
});
}
// 加载动画
Widget _getMoreWidget() {
// 如果还有数据
if(this._hasMore){
return Center(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'加载中',
style: TextStyle(fontSize: 16.0),
),
// 加载图标
CircularProgressIndicator(
strokeWidth: 1.0,
)
],
),
),
);
}else{
return Center(
child: Text("...我是有底线的..."),
);
}
}
@override
Widget build(BuildContext context) {
return Container(
child:Scaffold(
appBar: AppBar(
title:Text("新闻列表")
),
body:this._list.length==0?this._getMoreWidget():RefreshIndicator(
child: ListView.builder(
// 上拉加载控制器
controller: _scrollController,
itemCount: this._list.length,
itemBuilder: (context,index){
Widget tip = Text("");
// 当渲染到最后一条数据时,加载动画提示
if(index == this._list.length-1){
tip = _getMoreWidget();
}
return Column(
children: <Widget>[
ListTile(
title:Text(
"${this._list[index]["title"]}",
maxLines:1,
)
),
Divider(),
// 加载提示
tip
],
);
},
),
// 下拉刷新事件
onRefresh:this._onRefresh
)
)
);
}
}
以下是下拉刷新的实现效果:
以下是上拉加载的实现效果: