- 下拉刷新需要用到RefreshIndicator组件,为属性onRefresh设置下拉时触发的方法即可
- 上拉加载关键是用ListView的控制器来实现
// 1. 定义滑动控制器变量
ScrollController _msgCtrl = ScrollController();
// 2. 在初始化勾子中添加下拉监听
@override
void initState() {
super.initState();
_msgCtrl.addListener(() {
if (_msgCtrl.position.pixels == _msgCtrl.position.maxScrollExtent) { // 下拉触发条件
_loadMore();
}
});
}
// 3. 在ListView中使用
ListView.builder(
itemCount: msgData.length + 1,
physics: const AlwaysScrollableScrollPhysics(),
controller: _msgCtrl,
itemBuilder: (context, index) {
if (index == msgData.length) {
return loadMoreBottom(hasMore);
} else {
return msgItem(msgData[index]);
}
},
)
完整代码如下:
import 'package:flutter/material.dart';
import 'package:annotation_route/route.dart';
import 'package:doctor_admin/config/common.dart';
import 'package:doctor_admin/route/route.dart';
@ARoute(url: 'page://myMsg/myMsg')
class MyMsg extends StatefulWidget {
final dynamic option;
MyMsg(this.option);
MyMsgState createState() => MyMsgState();
}
class MyMsgState extends State<MyMsg> {
int page = 0;
List msgData = [];
bool hasMore = true, isLoading = false;
ScrollController _msgCtrl = ScrollController();
Future _loadMore() async{
if(isLoading || !hasMore) return;
setState(() {
isLoading = true;
});
List newMsgs;
page++;
final res = await request(context, '/api/news/news_list', 'GET', params: {'page': page, 'size': 10});
setState(() {
isLoading = false;
});
if(res == null) return;
hasMore = res.data['data']['hasNextPage'];
newMsgs = res.data['data']['list'];
printWrapped(newMsgs.toString());
if(page > 1) {
msgData.addAll(newMsgs);
}else {
msgData = newMsgs;
}
setState(() {
page = page;
hasMore = hasMore;
// msgData = result;
});
}
Future _refresh() async {
if(isLoading) return;
// msgData.clear();
setState(() {
page = 0;
hasMore = true;
});
await _loadMore();
}
String getSimpleText(html){
var re1 = new RegExp("<.+?>");//匹配html标签的正则表达式,"g"是搜索匹配多个符合的内容
var msg = html.replaceAll(re1,'');//执行替换成空字符
return msg;
}
@override
void initState() {
super.initState();
_loadMore();
_msgCtrl.addListener(() {
if (_msgCtrl.position.pixels == _msgCtrl.position.maxScrollExtent) {
_loadMore();
}
});
}
Widget msgItem(item) {
return ClickView(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){
return AppRoute.getPage('page://myMsg/myMsgDetail', {'msgId': item['id']});
}));
},
margin: EdgeInsets.only(top: setSize(20)),
color: Colors.white,
radius: setSize(8),
child: Container(
height: setSize(200),
padding: EdgeInsets.fromLTRB(setSize(18), setSize(20), setSize(20), setSize(18)),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(item['createTime'], style: TextStyle(color: Color(0xffcccccc), fontSize: setFont(22), fontWeight: FontWeight.w400, height: 15/11),),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: setSize(564),
height: setSize(84),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: setSize(22)),
child: Text(item['title'], style: TextStyle(color: Color(0xff4a4a4a), fontSize: setFont(28), fontWeight: FontWeight.w500, height: 20/14), maxLines: 1, overflow: TextOverflow.ellipsis,),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: setSize(14),
height: setSize(14),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(setSize(7)),
color: Colors.transparent
),
),
SizedBox(width: setSize(10),),
Expanded(
child: Text(getSimpleText(item['content']), style: TextStyle(color: Color(0xff666666), fontSize: setFont(22), fontWeight: FontWeight.w500, height: 16/11), maxLines: 1, overflow: TextOverflow.ellipsis,),
)
],
)
],
),
),
nextPageArr()
],
)
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('我的消息', style: TextStyle(color: Color(0xff4a4a4a), fontSize: setFont(32), fontWeight: FontWeight.w500)),
leading: goBackArr(context, isBlack: true),
elevation: 0,
),
body: Container(
width: setFullWidth(context),
height: setFullHeight(context),
padding: EdgeInsets.symmetric(vertical: 0, horizontal: setSize(32)),
color: Color(0xffF9F9F9),
child: RefreshIndicator(
onRefresh: _refresh,
child: msgData.length > 0 ? ListView.builder(
itemCount: msgData.length + 1,
physics: const AlwaysScrollableScrollPhysics(),
controller: _msgCtrl,
itemBuilder: (context, index) {
if (index == msgData.length) {
return loadMoreBottom(hasMore);
} else {
return msgItem(msgData[index]);
}
},
) : (isLoading ?
LoadingView(context: context,) :
blankView(context, getAssetImage('blank_msg.png'), '暂无消息哦~'))
),
)
);
}
}