Flutter_学习记录_实现列表上拉加载更多的功能

可以用ScrollController组件来实现这样列表上拉加载更多的功能:
请添加图片描述

1. 定义变量

StatefulWidget 的组件内,添加三个属性:

// 滚动视图的控制器final ScrollController _scrollController = ScrollController();// 是否已显示了上拉加载中bool _isShowMore = false;// 是否有更多的数据bool _isHaveMoreData = true;

2. 在初始化的方法中,添加对ScrollController的监听

重写initState的方法,并在initState方法中,添加ScrollController的监听,代码如下:

void initState() {super.initState();// 对 _scrollController 添加监听_scrollController.addListener((){// 内容视图最大的高度double maxScrollExtent = _scrollController.position.maxScrollExtent;// 视图滚动的大小double scrollContentOffY = _scrollController.position.pixels;if (scrollContentOffY > maxScrollExtent + Screenadapter.height(40)) {// 超出了内容视图高度的20,就重新上拉加载更多if (_isShowMore == false && _isHaveMoreData == true) {// 未显示, print("上拉加载更多");// 添加网络请求_getProductListDataRequest();}}});

3. 在ListView中,关联ScrollController

代码如下:

ListView.builder(// 关联 ScrollControllercontroller: _scrollController,itemBuilder: (BuildContext context, int index) {return Column();}
)

4. 写一个简易的Loading的加载视图

代码如下:

import 'package:fangjd/Services/ScreenAdapter.dart';
import 'package:flutter/material.dart';class Loadingwidget extends StatelessWidget {const Loadingwidget({super.key});Widget build(BuildContext context) {return Center(child: Container(padding: EdgeInsets.all(Screenadapter.width(20)),child: Row(mainAxisAlignment: MainAxisAlignment.center,children: [CircularProgressIndicator(strokeWidth: 1.0),SizedBox(width: Screenadapter.width(20)),Text("加载中....")],),),);}
}

5. 在列表的底部视图,添加加载中的视图或者添加我是我底线的视图

代码如下:

// 商品列表底部的视图Widget _productBottomWiget(int index) {if (_isHaveMoreData == true) {// 如果有更多的数据,上拉,就显示“加载中”, 其中_productList 是数据源if (_isShowMore && (index == _productList.length -1)) {// 只有最后一个数据,才添加 “加载中”的loading视图return Loadingwidget();} else {// 其他数据 就什么都不显示return SizedBox(height: 1);}} else {// 如果没有更多的数据,if (index == _productList.length -1) {// 在最后一个数据,添加 “--我也是有底线的--”的视图return Padding(padding:EdgeInsets.only(top: Screenadapter.height(30)), child: Text("--我也是有底线的--", textAlign: TextAlign.center,));} else {// 其他数据 就什么都不显示return SizedBox(height: 1);}}}

6. 模拟网络数据的请求

代码如下:

// -----网络请求--------void _getProductListDataRequest() async {setState(() {// 当调用网络请求的时候,设置_isShowMore 为 true, 表示需要展示“加载中”的底部视图_isShowMore = true;});// 模拟网络延迟await Future.delayed(Duration(seconds: 2)); List<ProductItemModel> mockDataList = _mockData();setState(() {_productList.addAll(mockDataList);// 等网路请求成功后,设置 _isShowMore 为 false, 表示 隐藏 “加载中”的底部视图_isShowMore = false;if (_productList.length > 20) {// 模拟没有更多数据了,就展示“我是有底线的”的视图 _isHaveMoreData = false;}});}// 模拟数据List<ProductItemModel> _mockData() {// returnList<ProductItemModel> mockList = [];for (var index in [1,2,3,4,5,6,7,8,9,0]) {var model = ProductItemModel(iId: 1, title: '笔记本电脑$index', price: "¥3980", oldPrice: "¥4999", pic: "https://www.itying.com/images/flutter/hot${index+1}.jpg");mockList.add(model);}return mockList;}

7. 完整的代码实例

import 'package:fangjd/CommonWidget/LoadingWidget.dart';
import 'package:fangjd/Models/ProductModel.dart';
import 'package:fangjd/Services/ScreenAdapter.dart';
import 'package:flutter/material.dart';class ProductlistPage extends StatefulWidget {const ProductlistPage({super.key});State<ProductlistPage> createState() => _ProductlistPageState();
}class _ProductlistPageState extends State<ProductlistPage> {// ScaffoldState, 控制侧边栏的显示final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();// 筛选导航栏的索引int _selectIndex = 1;// 商品列表的数据List<ProductItemModel> _productList = [];// 滚动视图的控制器final ScrollController _scrollController = ScrollController();// 是否已显示了上拉加载中bool _isShowMore = false;// 是否有更多的数据bool _isHaveMoreData = true;void initState() {super.initState();_scrollController.addListener((){// 内容视图最大的高度double maxScrollExtent = _scrollController.position.maxScrollExtent;// 视图滚动的大小double scrollContentOffY = _scrollController.position.pixels;if (scrollContentOffY > maxScrollExtent + Screenadapter.height(40)) {// 超出了内容视图高度的20,就重新上拉加载更多if (_isShowMore == false && _isHaveMoreData == true) {// 未显示_getProductListDataRequest();}}});// -----网络请求--------_getProductListDataRequest();}// -----网络请求--------void _getProductListDataRequest() async {setState(() {_isShowMore = true;});// 模拟网络延迟await Future.delayed(Duration(seconds: 2)); List<ProductItemModel> mockDataList = _mockData();setState(() {_productList.addAll(mockDataList);_isShowMore = false;if (_productList.length > 20) {_isHaveMoreData = false;}});}// 模拟数据List<ProductItemModel> _mockData() {// returnList<ProductItemModel> mockList = [];for (var index in [1,2,3,4,5,6,7,8,9,0]) {var model = ProductItemModel(iId: 1, title: '笔记本电脑$index', price: "¥3980", oldPrice: "¥4999", pic: "https://www.itying.com/images/flutter/hot${index+1}.jpg");mockList.add(model);}return mockList;}// -----视图设置--------// 设置 筛选透视图的底部选中的线Border _selectHeaderBoder() {return Border(bottom: BorderSide(width: 1,color: Colors.red));}// 筛选导航栏Widget _subHeaderWidget() {return Positioned(top: 0.0,child: Container(height: Screenadapter.height(80),width: Screenadapter.screenWidth(),decoration: BoxDecoration(border: Border(bottom: BorderSide(width: 1,color: Colors.black12),),),child: Row(children: [Expanded(child: InkWell(onTap: () {setState(() {_selectIndex = 1;});},child: Container(decoration: BoxDecoration(border: _selectIndex == 1 ? _selectHeaderBoder() : null),child: Center(child: Text("综合", style: TextStyle(color: _selectIndex == 1 ? Colors.red : Colors.black))),),)),Expanded(child: InkWell(onTap: () {setState(() {_selectIndex = 2;});},child: Container(decoration: BoxDecoration(border: _selectIndex == 2 ? _selectHeaderBoder() : null),child: Center(child: Text("销量", style: TextStyle(color: _selectIndex == 2 ? Colors.red : Colors.black))),),)),Expanded(child: InkWell(onTap: () {setState(() {_selectIndex = 3;});},child: Container(decoration: BoxDecoration(border: _selectIndex == 3 ? _selectHeaderBoder() : null),child: Center(child: Text("价格", style: TextStyle(color: _selectIndex == 3 ? Colors.red : Colors.black))),),)),Expanded(child: InkWell(onTap: () {setState(() {_selectIndex = 4;});_scaffoldKey.currentState?.openEndDrawer();},child: Container(decoration: BoxDecoration(border: _selectIndex == 4 ? _selectHeaderBoder() : null),child: Center(child: Text("筛选", style: TextStyle(color: _selectIndex == 4 ? Colors.red : Colors.black))),),)),],),));}// 商品列表底部的视图Widget _productBottomWiget(int index) {if (_isHaveMoreData == true) {if (_isShowMore && (index == _productList.length -1)) {return Loadingwidget();} else {return Text("");}} else {if (index == _productList.length -1) {return Padding(padding:EdgeInsets.only(top: Screenadapter.height(30)), child: Text("--我也是有底线的--", textAlign: TextAlign.center,));} else {return SizedBox(height: 1);}}}// 商品列表Widget _productListWidget() {if (_productList.isNotEmpty) {return  Container(padding: EdgeInsets.all(Screenadapter.width(10)),margin: EdgeInsets.only(top: Screenadapter.height(80)),child: ListView.builder(controller: _scrollController,itemBuilder: (BuildContext context, int index) {ProductItemModel itemModel = _productList[index];return Column(children: [Row(children: [Container(padding: EdgeInsets.all(Screenadapter.width(20)),width: Screenadapter.width(220),height: Screenadapter.height(220),child: AspectRatio(aspectRatio: 1,child: Image.network(itemModel.pic, fit: BoxFit.cover)),),Expanded(child: Container(height: Screenadapter.height(220),padding: EdgeInsets.only(top: Screenadapter.height(10)),child: Column(mainAxisAlignment: MainAxisAlignment.start,crossAxisAlignment: CrossAxisAlignment.start,children: [Text(itemModel.title,maxLines: 2,overflow: TextOverflow.ellipsis,),SizedBox(height: Screenadapter.height(20)),Container(height: Screenadapter.height(36),width: double.infinity,child: Row(children: [Container(height: Screenadapter.height(40),width: Screenadapter.width(80),decoration: BoxDecoration(borderRadius: BorderRadius.circular(Screenadapter.height(18)),color: Colors.black12),child: Center(child: Text(' 4G ', style: TextStyle(color: Colors.black87))),),SizedBox(width: Screenadapter.width(20)),Container(height: Screenadapter.height(40),width: Screenadapter.width(80),decoration: BoxDecoration(borderRadius: BorderRadius.circular(Screenadapter.height(18)),color: Colors.black12),child: Center(child: Text(' 126 ', style: TextStyle(color: Colors.black87))),),],),),SizedBox(height: Screenadapter.width(20)),Text(itemModel.price, style: TextStyle(color: Colors.red, fontSize: 18))])))],),Divider(height: Screenadapter.height(2)),// 添加列表底部视图:显示“加载中”还是显示“我是有底线的”_productBottomWiget(index)],);},itemCount: _productList.length),);} else {return Loadingwidget();}}Widget build(BuildContext context) {return Scaffold(key: _scaffoldKey,appBar: AppBar(title: Text("商品分类"),actions: [// 去掉’endDrawer‘默认设置的图标Text("")],),endDrawer: Drawer(child: Center(child: Text("我是侧边栏")),),body: Stack(children: [// 筛选导航栏_subHeaderWidget(),// 商品列表_productListWidget()],),);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】【网络】不同子网下的客户端和服务器通信其它方式

【Linux】【网络】不同子网下的客户端和服务器通信其它方式 那么&#xff0c;在 NAT 环境下&#xff0c;应该如何让内网设备做为服务器&#xff0c;使内网设备被外部连接&#xff1f; 1 多拨 部分运营商&#xff0c;支持在多个设备上&#xff0c;通过 PPPoE 登录同一个宽带账…

《Python百练成仙》31-40章(不定时更新)

第卅一章 函数结丹def开紫府 罗酆山的鬼门关吞吐着猩红的变量阴风&#xff0c;每个风眼都涌动着作用域混乱的灵力乱流。叶军手握薛香遗留的丹田玉简&#xff0c;玉简表面浮现出残缺的函数符文&#xff1a; def 凝聚金丹(灵气):道基 灵气 * 0.618print(金丹品质) # 作用域外变…

六十天前端强化训练之第一天到第七天——综合案例:响应式个人博客项目

欢迎来到编程星辰海的博客讲解 目录 前言回顾 HTML5与CSS3基础 一、知识讲解 1. 项目架构设计&#xff08;语义化HTML&#xff09; 2. 响应式布局系统&#xff08;Flex Grid&#xff09; 3. 样式优先级与组件化设计 4. 完整响应式工作流 二、核心代码示例 完整HTML结…

测试的BUG分析

在了解BUG之前,我们要先了解软件测试的生命周期,因为大多数BUG都是在软件测试的过程中被发现的 软件测试的生命周期 在了解 软件测试的生命周期 之前,我们要先了解 软件的生命周期 ,虽然他们之间只差了两个字,但是差距还是很大的 首先是 软件生命周期 ,这个是站在 软件 的角…

【洛谷贪心算法题】P1094纪念品分组

该题运用贪心算法&#xff0c;核心思想是在每次分组时&#xff0c;尽可能让价格较小和较大的纪念品组合在一起&#xff0c;以达到最少分组的目的。 【算法思路】 输入处理&#xff1a;首先读取纪念品的数量n和价格上限w&#xff0c;然后依次读取每件纪念品的价格&#xff0c;…

[STM32]从零开始的STM32 BSRR、BRR、ODR寄存器讲解

一、前言 学习STM32一阵子以后&#xff0c;相信大家对STM32 GPIO的控制也有一定的了解了。之前在STM32 LED的教程中也教了大家如何使用寄存器以及库函数控制STM32的引脚从而点亮一个LED&#xff0c;之前的寄存器只是作为一个引入&#xff0c;并没有深层次的讲解&#xff0c;在教…

SQL分组问题

下列为电商公司用户访问时间数据 统计某个用户连续的访问记录&#xff0c;如果时间间隔小于60s&#xff0c;就分为一组 id ts 1001 17523641234 1001 17523641256 1002 17523641278 1001 17523641334 1002 17523641434 1001 17523641534 1001 17523641544 1002 17523…

3月2日 C++日常习题测试一答案

C测试题答案与讲解 一、填空题答案及讲解 答案&#xff1a;const 讲解&#xff1a;在 C 中&#xff0c;const关键字用于定义常量&#xff0c;一旦定义&#xff0c;其值不能被修改。例如const int num 10;&#xff0c;这里的num就是一个常量。 答案&#xff1a;3 讲解&…

2W8000字 LLM架构文章阅读指北

❝ 大模型架构专栏已经更新了30多篇文章。完整的专栏内容欢迎订阅&#xff1a; LLM 架构专栏 1、LLM大模型架构专栏|| 从NLP基础谈起 2、 LLM大模型架构专栏|| 自然语言处理&#xff08;NLP&#xff09;之建模 3、 LLM大模型架构之词嵌入&#xff08;Part1&#xff09; 3、 LLM…

SP导入智能材质球

智能材质球路径 ...\Adobe Substance 3D Painter\resources\starter_assets\smart-materials 放入之后就会自动刷新

网络原理----TCP/IP(3)

核心机制七----延时应答 默认情况下&#xff0c;接收方都是在收到数据报的第一时间&#xff0c;就返回ack&#xff0c;但是可以通过延时返回ack的方式来提高效率&#xff0c;理论上不是100%提高效率&#xff0c;但还是有一定帮助的。 因为如果接收数据的主机⽴刻返回ACK应答,…

MacBook Pro使用FFmpeg捕获摄像头与麦克风推流音视频

FFmpeg查看macos系统音视频设备列表 ffmpeg -f avfoundation -list_devices true -i "" 使用摄像头及麦克风同时推送音频及视频流: ffmpeg -f avfoundation -pixel_format yuyv422 -framerate 30 -i "0:1" -c:v libx264 -preset ultrafast -b:v 1000k -…

部署Joplin私有云服务器postgres版-docker compose

我曾经使用过一段时间 Joplin&#xff0c;官方版本是收费的&#xff0c;而我更倾向于将数据掌握在自己手中。因此&#xff0c;在多次权衡后&#xff0c;我决定自己搭建 Joplin 服务器并进行尝试。 个人搭建的版本与数据库直连&#xff0c;下面是使用 Docker Compose 配置数据库…

SQL的select语句完整的执行顺序

SQL的SELECT语句的执行顺序可以用"做菜流程"来类比理解。虽然我们写SQL时按SELECT…FROM…WHERE…顺序写&#xff0c;但数据库执行顺序完全不同。以下是通俗易懂的讲解&#xff08;附流程图和示例&#xff09;&#xff1a; &#x1f527; 执行顺序流程图&#xff1a…

Spring Cloud LoadBalancer详解

一、介绍 Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客户端负载均衡器,抽象和实现,用来替代Ribbon(已经停更), 二、Ribbon和Loadbalance 对比 组件组件提供的负载策略支持负载的客户端Ribbon随机 RandomRule轮询 RoundRobinRule 重试 RetryRule最低并发 Bes…

ubuntu中ollama设置记录

自己同一台电脑主机安装3080和3090显卡&#xff0c;测试发现ollama只默认跑在3090上&#xff1b;故查看一下设置&#xff0c;成功也把3080也运行起来了。 原因如下&#xff1a; 开始设置记录&#xff1a; Environment Variables: OLLAMA_DEBUG 作用&#xff1a;显示额外的调试…

RabbitMQ系列(四)基本概念之Exchange

在 RabbitMQ 中&#xff0c;Exchange&#xff08;交换机&#xff09; 是消息路由的核心组件&#xff0c;负责根据规则将生产者发送的消息分发到对应的队列&#xff08;Queue&#xff09;中。以下是其核心功能与分类的详细说明&#xff1a; 一、Exchange 的核心作用 消息路由枢…

有没有什么免费的AI工具可以帮忙做简单的ppt?

互联网各领域资料分享专区(不定期更新): Sheet 正文 1. 博思AIPPT 特点:专为中文用户设计,支持文本/文件导入生成PPT,内置海量模板和智能排版功能,涵盖商务、教育等多种场景。可一键优化布局、配色,并集成AI绘图功能(文生图/图生图)。适用场景:职场汇报、教育培训、商…

【Python · PyTorch】循环神经网络 RNN(基础应用)

【Python PyTorch】循环神经网络 RNN&#xff08;简单应用&#xff09; 1. 简介2. 模拟客流预测&#xff08;数据集转化Tensor&#xff09;3.1 数据集介绍3.2 训练过程 3. 模拟股票预测&#xff08;DataLoader加载数据集&#xff09;3.1 IBM 数据集3.1.2 数据集介绍3.1.3 训练…

【JSON2WEB】15 银河麒麟操作系统下部署JSON2WEB

【JSON2WEB】系列目录 【JSON2WEB】01 WEB管理信息系统架构设计 【JSON2WEB】02 JSON2WEB初步UI设计 【JSON2WEB】03 go的模板包html/template的使用 【JSON2WEB】04 amis低代码前端框架介绍 【JSON2WEB】05 前端开发三件套 HTML CSS JavaScript 速成 【JSON2WEB】06 JSO…