- 下拉刷新需要用到RefreshIndicator组件,为属性onRefresh设置下拉时触发的方法即可
 - 上拉加载关键是用ListView的控制器来实现
// 1. 定义滑动控制器变量ScrollController _msgCtrl = ScrollController();// 2. 在初始化勾子中添加下拉监听@overridevoid 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;}@overridevoid 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()],)],),),);}@overrideWidget 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'), '暂无消息哦~'))),));}}
