Flutter ListView 上拉加載更多下拉刷新功能實(shí)現(xiàn)方法
先上圖
下拉刷新
跟原生開(kāi)發(fā)一樣,下拉刷新在flutter
里提供的有組件實(shí)現(xiàn) RefreshIndicator
一直不明白為啥組件中都提供下拉刷新,但就是沒(méi)有上拉加載??!
我這請(qǐng)求接口數(shù)據(jù)用的是 http 庫(kù),是個(gè)第三方的是需要安裝的 https://pub.dev/packages/http
用法如下
class MyHomePage extends StatefulWidget { MyHomePage({Key key}) : super(key: key); @override MyHomeWidget2 createState() => MyHomeWidget2(); } class MyHomeWidget2 extends State<MyHomePage> { int page = 1; List data = new List(); var baseUrl = "https://cnodejs.org/api/v1"; @override void initState() { super.initState(); this._onRefresh(); } _fetchData() async { var response = await http.get( '${this.baseUrl}/topics?mdrender=false&limit=10&page=${this.page}'); var json = await convert.jsonDecode(response.body); return json['data']; } Future<dynamic> _onRefresh() { data.clear(); this.page = 1; return _fetchData().then((data) { setState(() => this.data.addAll(data)); }); } @override Widget build(BuildContext context) { return Scaffold( body: RefreshIndicator( // 在ListView外包一層 RefreshIndicator 組件 onRefresh: _onRefresh, // 添加onRefresh方法 child: ListView.separated( itemCount: this.data.length, itemBuilder: (context, index) { var _data = this.data[index]; return ListTile( leading: Image.network(_data["author"]["avatar_url"]), title: Text(_data["title"]), subtitle: Text(_data["author"]["loginname"] + " created at " + new DateTime.now().toString()), // 為了看每次數(shù)據(jù)變動(dòng),這里直接取當(dāng)前時(shí)間 trailing: Icon(Icons.chevron_right)); }, separatorBuilder: (context, index) { return Divider(); }, ) )); } }
鏈接文原: https://tomoya92.github.io/2019/07/17/flutter-refresh-loadmore/
上拉加載
上拉加載原理還是一樣的,給ListView加一個(gè) ScrollController 組件,然后通過(guò)事件監(jiān)聽(tīng)滾動(dòng)條的高度來(lái)顯示和隱藏加載更多的組件
先將加載更多的組件寫(xiě)好
Widget _loadMoreWidget() { return new Padding( padding: const EdgeInsets.all(15.0), // 外邊距 child: new Center( child: new CircularProgressIndicator() ), ); }
初始化一個(gè) ScrollController
組件,將其設(shè)置給 ListView 組件的 controller 屬性上
ScrollController _scrollController = new ScrollController(); child: ListView.separated( controller: _scrollController, //... )
然后通過(guò)重寫(xiě) dispost() 方法來(lái)處理加載更多組件的釋放
@override void dispose() { _scrollController.dispose(); super.dispose(); }
最后通過(guò)數(shù)據(jù)源來(lái)控制界面渲染哪個(gè)組件,當(dāng)數(shù)據(jù)源循環(huán)渲染的 index 跟數(shù)據(jù)源一樣長(zhǎng)時(shí)(其實(shí)少1,下標(biāo)從0開(kāi)始的)就渲染加載更多組件,讓其顯示出來(lái),同時(shí)調(diào)用加載更多方法,獲取數(shù)據(jù),再通過(guò)state實(shí)現(xiàn)組件ui的更新
完整代碼如下
class MyHomePage extends StatefulWidget { MyHomePage({Key key}) : super(key: key); @override MyHomeWidget2 createState() => MyHomeWidget2(); } class MyHomeWidget2 extends State<MyHomePage> { int page = 1; bool isLoadmore = false; List data = new List(); var baseUrl = "https://cnodejs.org/api/v1"; ScrollController _scrollController = new ScrollController(); @override void initState() { super.initState(); this._onRefresh(); _scrollController.addListener(() { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { _onLoadmore(); } }); } _fetchData() async { var response = await http.get( '${this.baseUrl}/topics?mdrender=false&limit=10&page=${this.page}'); var json = await convert.jsonDecode(response.body); return json['data']; } Future<dynamic> _onRefresh() { data.clear(); this.page = 1; return _fetchData().then((data) { setState(() => this.data.addAll(data)); }); } Future<dynamic> _onLoadmore() { this.page++; return _fetchData().then((data) { setState((){ this.data.addAll(data); isLoadmore = false; }); }); } @override void dispose() { _scrollController.dispose(); super.dispose(); } Widget _loadMoreWidget() { return new Padding( padding: const EdgeInsets.all(15.0), child: new Center( child: new CircularProgressIndicator() ), ); } @override Widget build(BuildContext context) { return Scaffold( body: RefreshIndicator( onRefresh: _onRefresh, child: ListView.separated( controller: _scrollController, itemCount: this.data.length, itemBuilder: (context, index) { if (index == data.length - 1) { return _loadMoreWidget(); } else { var _data = this.data[index]; return ListTile( leading: Image.network(_data["author"]["avatar_url"]), title: Text(_data["title"]), subtitle: Text(_data["author"]["loginname"] + " created at " + new DateTime.now().toString()), trailing: Icon(Icons.chevron_right)); } }, separatorBuilder: (context, index) { return Divider(); }, ) )); } }
總結(jié)
以上所述是小編給大家介紹的Flutter ListView 上拉加載更多下拉刷新功能實(shí)現(xiàn)方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
sharding-jdbc實(shí)現(xiàn)分頁(yè)查詢(xún)的示例代碼
sharding-jdbc是一個(gè)輕量級(jí)Java框架,它提供了分布式數(shù)據(jù)庫(kù)中間件的功能,支持水平分表和分庫(kù)分表,在分頁(yè)查詢(xún)方面,sharding-jdbc支持兩種方式:基于物理分頁(yè)和基于邏輯分頁(yè),本文給大家介紹sharding-jdbc如何實(shí)現(xiàn)分頁(yè)查詢(xún),需要的朋友可以參考下2024-05-05mybatis generator只能生成insert和selectAll的操作
這篇文章主要介紹了mybatis generator只能生成insert和selectAll的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09MyBatis完成CRUD?詳細(xì)細(xì)節(jié)內(nèi)容剖析
這篇文章主要介紹了MyBatis完成CRUD?詳細(xì)細(xì)節(jié)內(nèi)容剖析,本文通過(guò)圖文示例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-05-05Spring boot + LayIM + t-io 實(shí)現(xiàn)文件上傳、 監(jiān)聽(tīng)用戶(hù)狀態(tài)的實(shí)例代碼
這篇文章主要介紹了Spring boot + LayIM + t-io 實(shí)現(xiàn)文件上傳、 監(jiān)聽(tīng)用戶(hù)狀態(tài)的實(shí)例代碼,需要的朋友可以參考下2017-12-12Java SpringBoot模板引擎之 Thymeleaf入門(mén)詳解
jsp有著強(qiáng)大的功能,能查出一些數(shù)據(jù)轉(zhuǎn)發(fā)到JSP頁(yè)面以后,我們可以用jsp輕松實(shí)現(xiàn)數(shù)據(jù)的顯示及交互等,包括能寫(xiě)Java代碼。但是,SpringBoot首先是以jar的方式,不是war;其次我們的tomcat是嵌入式的,所以現(xiàn)在默認(rèn)不支持jsp2021-10-10關(guān)于springboot中的自定義配置項(xiàng)
這篇文章主要介紹了關(guān)于springboot中的自定義配置項(xiàng),在項(xiàng)目開(kāi)發(fā)的過(guò)程中,經(jīng)常需要自定義系統(tǒng)業(yè)務(wù)方面的配置文件及配置項(xiàng),Spring Boot提供了@value注解、@ConfigurationProperties注解和Environment接口等3種方式自定義配置項(xiàng),需要的朋友可以參考下2023-07-07