Flutter下拉刷新和上拉加载更多

Flutter下拉刷新和上拉加载更多

下拉刷新直接用flutter自带的控件RefreshIndicator组件即可,上拉加载可以通过ListView 中的ScrollController 属性,根据 ListView 的位置来判断是否滑动到了底部来做加载更多的处理
下面用们用到的json数据接口为:https://jsonplaceholder.typicode.com/posts/1/comments

下拉刷新

就是在我们上一节讲到的解析的列表外面嵌套一个RefreshIndicator,然后通过onRefresh进行监听

  @override
  Widget build(BuildContext context) {
    
    
    return Scaffold(
        appBar: AppBar(
          title: Text("请求数据 Dio Demo"),
        ),
        body: this._list.length > 0
            ? RefreshIndicator(
                onRefresh: _onRefresh,
                child: ListView.builder(
                    itemCount: this._list.length,
                    itemBuilder: (context, index) {
    
    
                      return ListTile(
                              title: Text(_list[index]["email"], maxLines: 1),
                            ));
                    }))
            : Text("加载中..."));
  }

  Future<void> _onRefresh() async {
    
    
    print('执行刷新');
    _getData();
    await Future.delayed(Duration(seconds: 3), () {
    
    
      print('refresh');
    });
  }

  _getData() async {
    
    
    var apiUrl = "https://jsonplaceholder.typicode.com/posts/${_page}/comments";
    Response result = await Dio().get(apiUrl);
    setState(() {
    
    
      _list.addAll(result.data);
      _page++;
    });
    print("获取数据操作");
  }

上拉加载更多

通过ListView 中的ScrollController 属性,根据 ListView 的位置来判断是否滑动到了底部来做加载更多的处理
_scrollController.position.pixels 滚动的距离
_scrollController.position.maxScrollExtent 总距离
自定义下部加载的控件

 Widget _getMoreWidget() {
    
    
    return Center(
      child: Padding(
        padding: EdgeInsets.all(10.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Text(
              '加载中...',
              style: TextStyle(fontSize: 16.0),
            ),
            CircularProgressIndicator(
              strokeWidth: 1.0,
            )
          ],
        ),
      ),
    );
  }
 ScrollController _scrollController = ScrollController(); //listview 的控制器
  List _list = [];
  int _page = 1;
  bool isLoading = false;

  @override
  void initState() {
    
    
    super.initState();
    _getData();
    //监听划到最底部就进行if内的操作
    _scrollController.addListener(() {
    
    
      if (_scrollController.position.pixels >
          _scrollController.position.maxScrollExtent - 20) {
    
    
        print('滑动到了最底部');
        _getData();
      }
    });
  }
ListView.builder(
                    itemCount: _list.length,
                    controller: _scrollController,
                    itemBuilder: (context, index) {
    
    
                      if (index == _list.length - 1) {
    
    
                        return Column(
                          children: <Widget>[
                            ListTile(
                              title: Text(_list[index]["email"], maxLines: 1),
                            ),
                            Divider(),
                            //如果条目达到最底部,则还要展示一个加载圈
                            _getMoreWidget()
                          ],
                        );
                      } else {
    
    
                        //没有到达底部直接加载条目
                        return Column(
                          children: <Widget>[
                            ListTile(
                              title: Text(_list[index]["email"], maxLines: 1),
                            ),
                            Divider()
                          ],
                        );
                      }
                    }))

代码:

// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables, avoid_print, prefer_is_empty, slash_for_doc_comments, unnecessary_brace_in_string_interps, prefer_const_constructors_in_immutables, prefer_final_fields

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';

class LoadMorePage extends StatefulWidget {
    
    
  LoadMorePage({
    
    Key? key}) : super(key: key);

  @override
  _LoadMorePageState createState() => _LoadMorePageState();
}

class _LoadMorePageState extends State<LoadMorePage> {
    
    
  ScrollController _scrollController = ScrollController(); //listview 的控制器
  List _list = [];
  int _page = 1;
  bool isLoading = false;

  var json; //是否正在加载数据
  @override
  void initState() {
    
    
    super.initState();
    //之所以写三遍是因为我发现接口中每一页数据较少,第一次加载一页达不到底部,监听不到滑动
    _getData();
    _getData();
    _getData();
    print("到达了最底部。。。");
    //下面这个方法每次都底部都会执行,上面的代码只会执行一次
    _scrollController.addListener(() {
    
    
      if (_scrollController.position.pixels >
          _scrollController.position.maxScrollExtent - 20) {
    
    
        print('滑动到了最底部');
        _getData();
      }
    });
  }

  _getData() async {
    
    
    var apiUrl =
        "https://jsonplaceholder.typicode.com/posts/${_page}/comments";
    Response result = await Dio().get(apiUrl);
// print(json.decode(result.data)["result"]);
    setState(() {
    
    
      _list.addAll(result.data);
      _page++;
    });
  }

/**
* 加载更多时显示的组件,给用户提示
*/
  Widget _getMoreWidget() {
    
    
    return Center(
      child: Padding(
        padding: EdgeInsets.all(10.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Text(
              '加载中...',
              style: TextStyle(fontSize: 16.0),
            ),
            CircularProgressIndicator(
              strokeWidth: 1.0,
            )
          ],
        ),
      ),
    );
  }

  Future<void> _onRefresh() async {
    
    
    print('执行刷新');
// this._getData();
    await Future.delayed(Duration(seconds: 3), () {
    
    
      print('refresh');
    });
  }

  @override
  Widget build(BuildContext context) {
    
    
    return Scaffold(
        appBar: AppBar(
          title: Text("请求数据"),
        ),
        body: _list.length > 0
            ? RefreshIndicator(
                onRefresh: _onRefresh,
                child: ListView.builder(
                    itemCount: _list.length,
                    controller: _scrollController,
                    itemBuilder: (context, index) {
    
    
                      if (index == _list.length - 1) {
    
    
                        return Column(
                          children: <Widget>[
                            ListTile(
                              title:
                                  Text(_list[index]["email"], maxLines: 1),
                            ),
                            Divider(),
                            //如果条目达到最底部,则还要展示一个加载圈
                            _getMoreWidget()
                          ],
                        );
                      } else {
    
    
                        //没有到达底部直接加载条目
                        return Column(
                          children: <Widget>[
                            ListTile(
                              title:
                                  Text(_list[index]["email"], maxLines: 1),
                            ),
                            Divider()
                          ],
                        );
                      }
                    }))
            : _getMoreWidget());
  }
}

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_46527751/article/details/122675587