簡單學(xué)習(xí)記錄下,flutter的簡單的上拉加載下拉刷新
效果圖
refresh.gif
上代碼
class RefreshWidget extends StatefulWidget {
@override
_RefreshState createState() {
return _RefreshState();
}
}
class _RefreshState extends State<RefreshWidget> {
// 用一個key來保存下拉刷新控件RefreshIndicator
GlobalKey<RefreshIndicatorState> _refreshKey = GlobalKey<RefreshIndicatorState>();
// 承載listView的滾動視圖
ScrollController _scrollController = ScrollController();
// 數(shù)據(jù)源
List<String> _dataSource = List<String>();
// 當前加載的頁數(shù)
int _pageSize = 0;
// 加載數(shù)據(jù)
void _loadData(int index) {
for (int i=0; i<15; i++) {
_dataSource.add((i+15*index).toString());
}
}
// 下拉刷新
Future<Null> _onRefresh() {
return Future.delayed(Duration(seconds: 2), () {
print("正在刷新...");
_pageSize = 0;
_dataSource.clear();
setState(() {
_loadData(_pageSize);
});
});
}
// 加載更多
Future<Null> _loadMoreData() {
return Future.delayed(Duration(seconds: 1), () {
print("正在加載更多...");
setState(() {
_pageSize++;
_loadData(_pageSize);
});
});
}
// 刷新
showRefreshLoading() {
new Future.delayed(const Duration(seconds: 0), () {
_refreshKey.currentState.show().then((e) {});
return true;
});
}
@override
void initState() {
showRefreshLoading();
_scrollController.addListener(() {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
_loadMoreData();
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
return RefreshIndicator(
key: _refreshKey,
onRefresh: _onRefresh,
child: ListView.separated(
controller: _scrollController,
padding: EdgeInsets.all(8.0),
physics: const AlwaysScrollableScrollPhysics(),
itemBuilder: (buildContext, index) {
return items(context, index);
},
itemCount: _dataSource.isEmpty ? 0 : _dataSource.length+1,
separatorBuilder: (buildContext, index) {
return Divider(
height: 1,
color: Colors.lightGreen,
);
},
),
);
}
// item控件
Widget items(context, index) {
if (index == _dataSource.length) {
return Container(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(
backgroundColor: Theme.of(context).primaryColor,
),
SizedBox(
width: 10.0,
),
Text(
"正在加載",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
color: Colors.deepPurple
),
)
],
),
)
),
);
}
return Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text.rich(TextSpan(
children: [
TextSpan(text: "我是第"),
TextSpan(
text: "${_dataSource[index]}",
style: TextStyle(
color: Colors.red,
fontSize: 18.0,
fontWeight: FontWeight.bold
)
),
TextSpan(text: "個")
]
)),
)
);
}
}
這里有段代碼
// 刷新
showRefreshLoading() {
new Future.delayed(const Duration(seconds: 0), () {
_refreshKey.currentState.show().then((e) {});
return true;
});
}
_refreshKey.currentState.show()
表示刷新時的頭部,他放在一個延時的異步操作中,當時還在考慮為什么放在異步里川尖,直接在initState
里調(diào)用不行么咧虎,試了一下庸疾,報錯仓手,錯誤日志是因為RefreshIndicator
為空,也就是圖層還沒渲染完成肠套,build方法還沒執(zhí)行完,這里加異步是為了等渲染完成后再進行操作猖任,即使延遲時間為0秒你稚。
另外注意RefreshIndicator
這個Widget,里面有一個onRefresh
屬性朱躺,他只接收一個Future對象刁赖,所以為什么這里下拉刷新,加載更多方法要設(shè)置返回值為Future长搀。
還有這里的itemCount
屬性為
_dataSource.isEmpty ? 0 : _dataSource.length+1
是當沒有數(shù)據(jù)時只有頂部圓圈存在宇弛,當有數(shù)據(jù)時,除了每條數(shù)據(jù)占據(jù)一行以外源请,當滑到最下面時枪芒,有一個加載widget占據(jù)一行。
另外還有flutter_easyrefresh刷新加載這個第三方巢钓,改天試試病苗。