Implement pull-down refresh and pull-up loading in Flutter

1. Pull down to refresh

The component RefreshIndicator is provided in Flutter for pull-down refresh.

The basic implementation method is to add an onRefresh event to the component, which will be triggered when the user pulls down to refresh. In this event, a delayed task Future.delayed( ) can be called to re-request data in the callback of the delayed task. That's it.

2. Pull up to load more

In Flutter, pull-up loading is mainly achieved by adding controllers using ListView.builder( )  .

The basic implementation method is to add a controller to the component, instantiate the ScrollController type controller when the component is initialized, and then in the initialized initState( ) , add addListener( ) to the controller to listen for events, and in the event callback function You can obtain the scrolling drop-down distance and the height of the entire page , and then determine the distance between these two values, and trigger a data request when the values ​​are approaching.

3. Code example

  1. import 'package:flutter/material.dart';
  2. import 'dart:convert';
  3. import 'package:dio/dio.dart';
  4. class NewsPage extends StatefulWidget {
  5. NewsPage({Key key}) : super(key: key);
  6. @override
  7. _NewsPageState createState() => _NewsPageState();
  8. }
  9. class _NewsPageState extends State<NewsPage> {
  10. // current page number
  11. int _page = 1;
  12. // page data
  13. List _list = [];
  14. // is there still
  15. bool _hasMore = true;
  16. // scroll controller
  17. ScrollController _scrollController = new ScrollController();
  18. @override
  19. void initState() {
  20. super.initState();
  21. this._getData();
  22. // listen for scroll events
  23. _scrollController.addListener((){
  24. // Get the scroll bar drop-down distance
  25. // print(_scrollController.position.pixels);
  26. // Get the height of the entire page
  27. // print(_scrollController.position.maxScrollExtent);
  28. if(_scrollController.position.pixels>_scrollController.position.maxScrollExtent-40){
  29. this._getData();
  30. }
  31. });
  32. }
  33. // get data list
  34. void _getData() async{
  35. if(this._hasMore){
  36. var url = "http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=${_page}";
  37. Response result = await Dio().get(url);
  38. var list = json.decode(result.data)["result"];
  39. setState (() {
  40. // concatenate data
  41. this._list.addAll(list);
  42. // Accumulate the number of pages
  43. this._page++;
  44. });
  45. if(list.length<20){
  46. setState (() {
  47. // close loading
  48. this._hasMore = false;
  49. });
  50. }
  51. }
  52. }
  53. // Pull down to refresh
  54. Future<void> _onRefresh() async{
  55. print ( "Pull to refresh" );
  56. // for two seconds
  57. await Future.delayed(Duration(milliseconds:2000),(){
  58. this._getData();
  59. });
  60. }
  61. // load animation
  62. Widget _getMoreWidget() {
  63. // if there is still data
  64. if(this._hasMore){
  65. return Center (
  66. child: Padding(
  67. padding: EdgeInsets.all(10.0),
  68. child: Row(
  69. mainAxisAlignment: MainAxisAlignment.center,
  70. crossAxisAlignment: CrossAxisAlignment.center,
  71. children: <Widget>[
  72. Text(
  73. 'Loading' ,
  74. style : TextStyle ( fontSize : 16.0 ),
  75. ),
  76. // load icon
  77. CircularProgressIndicator(
  78. strokeWidth: 1.0,
  79. )
  80. ],
  81. ),
  82. ),
  83. );
  84. }else{
  85. return Center (
  86. child : Text ( "...I am underlined..." ),
  87. );
  88. }
  89. }
  90. @override
  91. Widget build(BuildContext context) {
  92. return Container(
  93. child:Scaffold(
  94. appBar: AppBar(
  95. title : Text ( "News List" )
  96. ),
  97. body:this._list.length==0?this._getMoreWidget():RefreshIndicator(
  98. child: ListView.builder(
  99. // Pull up to load the controller
  100. controller: _scrollController,
  101. itemCount: this._list.length,
  102. itemBuilder: (context,index){
  103. Widget tip = Text("");
  104. // When the last piece of data is rendered, load the animation prompt
  105. if(index == this._list.length-1){
  106. tip = _getMoreWidget();
  107. }
  108. return Column (
  109. children: <Widget>[
  110. ListTile (
  111. title:Text(
  112. "${this._list[index]["title"]}",
  113. maxLines:1,
  114. )
  115. ),
  116. Divider(),
  117. // load prompt
  118. tip
  119. ],
  120. );
  121. },
  122. ),
  123. // pull down to refresh event
  124. onRefresh:this._onRefresh
  125. )
  126. )
  127. );
  128. }
  129. }

The following is the implementation effect of pull-down refresh:

The following is the implementation effect of pull-up loading:

Tags: Implement pull-down refresh and pull-up loading in Flutter

Flutter flutter android ios

Related: Implement pull-down refresh and pull-up loading in Flutter