zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

flutter:使用listview之三:上拉加载更多(flutter 3.7.0)

flutter 加载 listview 之三 3.7 上拉 使用
2023-09-14 09:01:15 时间

一,配置用到的第三方库

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  dio: ^4.0.6
  flutter_screenutil: ^5.6.1
  fluttertoast: ^8.1.3

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

         对应的源码可以访问这里获取: https://github.com/liuhongdi/
         或: https://gitee.com/liuhongdi

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,代码:

1,ListOne.dart

class ListOne {
  String title;
  String author;
  int id;

  ListOne(this.title,this.author, this.id) {}

  ListOne.fromJson(Map<String, dynamic>json)
      :title=json["title"],
        author = json["author"],
        id = json["id"];
}

2,list.dart

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:demolistmore/model/ListOne.dart';
import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluttertoast/fluttertoast.dart';


class ItemList extends StatefulWidget {
  @override
  _MyList  createState()=> _MyList();
}

//封装的动态页面类
class _MyList extends State<ItemList>{

  ScrollController _scrollController = ScrollController(); //listview 的控制器
  //存放数据
  List<ListOne> _listData=[];
  //当前第几页
  int _currentPage = 0;
  int _total = 1;

  //上拉加载更多的提示文本
  String loadMoreText = "正在加载中...";
  //上拉加载更多的样式
  TextStyle loadMoreTextStyle = new TextStyle(color: const Color(0xFF4483f6), fontSize: 14.0);

  //http方式获取数据
  Future<Null> getHttp() async{
    String url = 'http://api.lhdtest.com/item/list?page='+_currentPage.toString();
    print(url);
    try {
      var response = await Dio().get(url);
      //处理json到类中
      var resoMap=json.decode(response.toString());
      _total = resoMap['data']['total'];
      for (int i = 0; i < (resoMap['data']['list'].length); i++) {
        var itemOne = resoMap['data']['list'][i];
        ListOne goodsOne = new ListOne(itemOne['title'],itemOne['author'], itemOne['id']);
        _listData.add(goodsOne);
      }
      setState(() {
      });
    } catch (e) {
      print(e);
    }
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getHttp();
    _scrollController.addListener(() {
      print("_scrollController.addListener");
      if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
        print("开始加载数据:_currentPage:"+_currentPage.toString());
        print("开始加载数据:_total:"+_total.toString());
        //已经滑到底了
        if (_currentPage < _total) {
          //还有数据,加载下一页
          setState(() {
            loadMoreText = "正在加载中...";
            loadMoreTextStyle = new TextStyle(color: const Color(0xFF4483f6), fontSize: 14.0);
          });
          _loadMore();
        } else {
          setState(() {
            loadMoreText = "没有更多数据";
            loadMoreTextStyle = new TextStyle(color: const Color(0xFF999999), fontSize: 14.0);
          });
        }
      }
    });
  }

  //构造list的item
  Widget _buildRow(int index) {
      if (index == 5) {
          return _imageRow(index);
      } else {
          return _textRow(index);
      }
  }

  Widget _imageRow(int index) {
    String imageUrl = "https://images.taboola.com.cn/taboola/image/fetch/f_jpg%2Cq_auto%2Ch_350%2Cw_420%2Cc_fill%2Cg_faces:auto%2Ce_sharpen/http%3A//cdn.taboola.com/libtrc/static/thumbnails/7dc5d37f2949e30163c870e0e5585592.jpg";
    return Container(
      margin: EdgeInsets.all(0),
      color: Colors.white,
      child: Container(
        width:560.w,
        height:360.w,
        margin: EdgeInsets.fromLTRB(20.w, 20.w, 20.w, 0),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.all(Radius.circular(30.w)),
          color: Colors.grey.withAlpha(40),
        ),
        child:Row(
            children:[
              Container(width:20.w),
              Image.network(imageUrl,height: 320.w,),
            ]
        ),

        alignment: Alignment.centerLeft,
      ),
    );
  }


  Widget _textRow(int index) {
    //非最后一行
    return Container(
      margin: EdgeInsets.all(0),
      color: Colors.white,
      child: Container(
        width:560.w,
        height:160.w,
        margin: EdgeInsets.fromLTRB(20.w, 20.w, 20.w, 0),
        //color: Colors.cyan,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.all(Radius.circular(30.w)),
          color: Colors.grey.withAlpha(40),
        ),
        child:Row(
            children:[
              _titleWrapper(context, _listData[index].title),
              _authorWrapper(context, _listData[index].author),
            ]
        ),
      ),
    );
  }

  Widget _authorWrapper(BuildContext context, String text) {
    return Container(
      height: 160.w,
      width:150.w,
      margin: EdgeInsets.fromLTRB(0.w, 0, 0, 0),
      decoration: new BoxDecoration(
        //color: Colors.yellow,
      ),
      alignment: Alignment.centerLeft,
      child: Text(
        text,
        maxLines: 2,
        overflow: TextOverflow.ellipsis,
        style: Theme.of(context).textTheme.headline6,
      ),
    );
  }

  Widget _titleWrapper(BuildContext context, String text) {
    return Container(
      height: 160.w,
      width:500.w,
      margin: EdgeInsets.fromLTRB(20.w, 0, 0, 0),
      decoration: new BoxDecoration(
        //color: Colors.red,
      ),
      alignment: Alignment.centerLeft,
      child: Text(
        text,
        maxLines: 2,
        overflow: TextOverflow.ellipsis,
        style: Theme.of(context).textTheme.headline6,
      ),
    );
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var content;
    if (_listData.length == 0) {
      content = new Center(
        // 可选参数 child:
        child: new CircularProgressIndicator(),
      );
    } else {
      content = _contentList();
    }

    //设置尺寸(填写设计中设备的屏幕尺寸)如果设计基于750dp * 1334dp的屏幕
    ScreenUtil.init(
        context,
        designSize: Size(750, 1334)
    );

    return Scaffold(
      appBar: AppBar(title: Text('小学三年级部编版'),),
      body: content,
    );
  }
  Widget _contentList() {
    return Stack(
      children: [
        new RefreshIndicator(
            onRefresh: _onRefresh,
            child: ListView.builder(
              itemCount: _listData.length+1,  //增加了一个上拉加载更多的指示
              itemBuilder: (BuildContext context, int index) {
                if (index == _listData.length) {
                  return _buildProgressMoreIndicator();
                } else {
                  return getItem(context,index);
                }
              },
              controller: _scrollController,
            )),
      ],
    );
  }
  //显示上拉加载更多的指示
  Widget _buildProgressMoreIndicator() {
    return new Padding(
      padding: const EdgeInsets.all(15.0),
      child: new Center(
        child: new Text(loadMoreText, style: loadMoreTextStyle),
      ),
    );
  }

  //上拉加载更多的方法
  Future<void> _loadMore() async {
    print('加载更多');

    if (_currentPage >= _total) {
      Fluttertoast.showToast(
          msg: "已经到达最后一页",
          toastLength: Toast.LENGTH_LONG,
          //toastLength: 60,
          gravity: ToastGravity.CENTER,
          timeInSecForIosWeb: 1,
          backgroundColor: Colors.blue,
          textColor: Colors.white,
          fontSize: 20.0
      );
    } else {
      if (_currentPage < 1) {
        _currentPage = 1;
      }
      _currentPage += 1;

      getHttp();
      await Future.delayed(Duration(milliseconds: 250), () {
        print('refresh');
      });
    }
  }

  //下拉刷新执行
  Future<void> _onRefresh() async {
    print('执行刷新');
    this._listData.clear();
    _currentPage = 1;
    getHttp();
    await Future.delayed(Duration(milliseconds: 500), () {
      print('refresh');
    });
  }

  Widget getItem(BuildContext context,int index) {
    return new GestureDetector(
      child:_buildRow(index),
    );
  }
}

3,接口返回的数据形式:

三,测试效果

四,查看flutter的版本:

liuhongdi@liuhongdideMBP ~ % flutter --version
Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b06b8b2710 (2 weeks ago) • 2023-01-23 16:55:55 -0800
Engine • revision b24591ed32
Tools • Dart 2.19.0 • DevTools 2.20.1