flutter 仿淘宝推荐二级分类效果
先看效果


一开始 用的PageView 做的, 然后重写PageScrollPhysics一顿魔改, 最后发现还是有一些小bug。 后面又想到pageview 能做,listview肯定也能做,最后用ListView加GridView 把功能实现了。
listview 实现pageview 的分页滑动效果只需要给ListView设置 physics: const PageScrollPhysics()。
做一个功能最重要的是拆分。
1:第一页最多展示5个半,(其实那半个是第二页的一部分)第二页后最多展示 15个
2:高度随着滑动动态变化
高度变化很简单只要最外层的widget 高度是动态的就行
Container(height: state.height, // 动态变化decoration: const BoxDecoration(color: Colors.white,// borderRadius:// BorderRadius.only(bottomLeft: Radius.circular(8), bottomRight: Radius.circular(8)),),child: _buildSubcategory(context),)
_buildSubcategory 这里主要有一些数学计算,因为数据多少是不确定的,第一页只显示五个,默认第二页最多显示15个,后面第三页等等都是默认最多显示15个,当然子分类可能没那么多,基本就两页,但是公式可以通用,想分几页就几页,能支持就支持呗。
/// 构建子分类Widget _buildSubcategory(BuildContext context) => Stack(children: <Widget>[SizedBox(width: ScreenUtil.width,child: ListView.builder(key: ValueKey("ListView$id"),addAutomaticKeepAlives: true,padding: EdgeInsets.zero,scrollDirection: Axis.horizontal,physics: const PageScrollPhysics(),// physics: const NoInertiaScrollPhysics(),itemCount: state.listSubcategoryEntity.length < 6? 1: ((state.listSubcategoryEntity.length - 5) / 15).ceil() + 1,controller: controller.scrollController,itemBuilder: (context, index) {List<SubcategoryEntity> list = [];if (index == 0) {if(state.listSubcategoryEntity.length>5){list.addAll(state.listSubcategoryEntity.sublist(0, 5));}else{list.addAll(state.listSubcategoryEntity);}} else {list.addAll(state.listSubcategoryEntity.sublist(5 + (index - 1) * 15,state.listSubcategoryEntity.length > (5 + index * 15)? 5 + index * 15: state.listSubcategoryEntity.length));}return _buildSubcategoryWidget(context, index, list);},),),Align(alignment: Alignment.bottomCenter,child: widgetBuilder(id: DemandListPageWidgetId.subcategoryIndicator,builder: () => _buildSubcategoryIndicatorWidget(state.listSubcategoryEntity.length < 6? 1: ((state.listSubcategoryEntity.length - 5) / 15).ceil() +1,state.index),),)],);
至于第一页怎么漏出第二页的数据,很简单 把第一页的width宽度设置小一点就能漏出第二页。
为什么是ScreenUtil.width-40?你想减多少都可以。。。我只是觉得减40漏出的部分更好看一些。
_buildSubcategoryWidget(BuildContext context, int indexs, List<SubcategoryEntity> list) {return SizedBox(width: state.listSubcategoryEntity.length >5&&indexs==0?ScreenUtil.width-40:ScreenUtil.width,child: GridView.builder(key: ValueKey("GridView$id"),physics: const NeverScrollableScrollPhysics(),shrinkWrap: true,padding:state.listSubcategoryEntity.length >5&&indexs==0?const EdgeInsets.only(left: 10 , top: 8):const EdgeInsets.only(left: 0, top: 8),gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5,// crossAxisSpacing: 5,childAspectRatio:1.1,// mainAxisSpacing: 2),itemBuilder: (BuildContext context, int index) {return Ripple(onTap: () {controller.push(url: list[index].jumpUrl ?? "");},child: Column(mainAxisSize: MainAxisSize.min,children: [ImageBuild.network(list[index].image?.small ?? '',fit: BoxFit.fill,size: const Size(35, 35),placeholder: AppImage.commonPlaceholderIconSmall),const SizedBox(height: 2.0,),TextBuild.text(list[index].title?.content ?? "",style: AppTextStyleData( fontWeight: AppTextStyle.regular,fontSize: 14,color: AppColorData.hex(list[index].title?.fontColor ?? "#1E1E1E"),),textAlign: TextAlign.center,),],));},itemCount: indexs == 0? (state.listSubcategoryEntity.length < 5? state.listSubcategoryEntity.length: 5): (state.listSubcategoryEntity.length > 5 + indexs * 15? 15: (state.listSubcategoryEntity.length - (5 + (indexs - 1) * 15))),),);}
主要是监听滑动事件,然后动态改变高度
NotificationListener<ScrollNotification>(onNotification: (ScrollNotification sn) {if (sn.metrics.axis == Axis.horizontal) {if (sn is ScrollEndNotification) {// var currentPage = (math.max(0.0, clampDouble(sn.metrics.pixels, sn.metrics.minScrollExtent, sn.metrics.maxScrollExtent)) /// math.max(1.0, ScreenUtil.width)).round();// state.index = currentPage;// controller.widgetRebuild(DemandListPageWidgetId.subcategoryIndicator);} else {double progress = sn.metrics.pixels;if (0 < progress && progress <= ScreenUtil.width) {var multiple = state.listSubcategoryEntity.length>15 ? 1:0;if(state.listSubcategoryEntity.length<11){state.height = 80;}else{state.height = progress/ScreenUtil.width * ((multiple+1)*78)+80;}} else if (progress == 0) {state.height = 80;}var currentPage = (math.max(0.0, clampDouble(sn.metrics.pixels, sn.metrics.minScrollExtent, sn.metrics.maxScrollExtent)) /math.max(1.0, ScreenUtil.width)).round();state.index = currentPage; // 记录当前页数controller.widgetRebuild(DemandListPageWidgetId.subcategory); //刷新页面,自行替换}}return false;},child: child );
相关文章:
flutter 仿淘宝推荐二级分类效果
先看效果 一开始 用的PageView 做的, 然后重写PageScrollPhysics一顿魔改, 最后发现还是有一些小bug。 后面又想到pageview 能做,listview肯定也能做,最后用ListView加GridView 把功能实现了。 listview 实现pageview 的分页滑动…...
报错 - LangChain AgentExecutor - ‘function‘ object has no attribute ‘get‘
使用 AgentExecutor 调用了使用两个 tool 的agent,报一下错误: 如果 agent 只使用 一个tool,没有报错 File "/Users/xx/miniconda3/envs/env1/lib/python3.11/site-packages/pydantic/_internal/_validators.py", line 44, in sequ…...
【DIY小记】通过降低电压和Process Lasso工具优化CPU超频表现
又到了创作纪念日,秉承着笔耕不辍的理念,笔者还是继续分享一下DIY日常。 在上一篇文章当中,笔者介绍了一些作为新手小白超频CPU和NVIDIA显卡的经验。今天又有了更新,笔者通过降低CPU工作电压,并且结合Process Lasso对…...
3、Docker搭建MQTT及Spring Boot 3.x集成MQTT
一、前言 本篇主要是围绕着两个点,1、Docker 搭建单机版本 MQTT(EMQX),2、Spring Boot 3.x 集成 MQTT(EMQX); 而且这里的 MQTT(EMQX)的搭建也只是一个简单的过程&#x…...
六种定时任务记录
1、java自带的Timer Timer是java中自带的类。 优点:使用简单,缺点是当添加并执行多个任务时,前面任务的执行用时和异常将影响到后面任务。 Timer timer new Timer();timer.schedule(new TimerTask() {int i 0;Overridepublic void run() …...
Dos下编译环境搭建和C运行程序生成
文章目录 前言一、需要准备的Tool二、搭建步骤 前言 因为工作需要,需要搭建个Dos下的编译环境来进行Code App开发,如下记录下搭建过程。 一、需要准备的Tool 编译环境:Win10/win11 编译工具: DOSBox0.74 Turboc2.7z 二、搭建步骤 1.双击压…...
【MySQL】入门篇—SQL基础:数据查询语言(DQL):复杂的SELECT语句
在实际应用中,复杂的SELECT语句可以帮助我们从多个表中提取相关信息,进行数据分析,生成报告,甚至进行数据挖掘。 掌握复杂的SELECT语句对于数据分析师、数据库管理员和开发者来说是必不可少的技能。 应用场景: 多表查…...
Appium环境搭建、Appium连接真机
文章目录 一、安装Android SDK二、安装Appium-desktop三、安装Appium Inspector 一、安装Android SDK 首先需要安装jdk,这里就不演示安装jdk的过程了 SDK下载地址:Android SDK 下载 1、点击 Android SDK 下载 -> SKD Tools 2、选择对应的版本进行下…...
【X线源】关于滨松MCS2软件的说明
【X线源】关于滨松MCS2软件的说明 1.软件背景2.MCS2界面3.MCS2操作4.常见问题 1.软件背景 滨松为了方便客户将滨松MFX集成进自己的系统,滨松提供了MFX二次开发相关的信息和Demo代码。参考博客说明: 【X线源】关于滨松MFX二次开发demo示例简介 https://…...
【深度学习代码调试2】环境配置篇(中) -- 列出conda环境中所有env的pytorch版本
【深度学习代码调试2】环境配置篇(中) -- 列出conda环境中所有env的pytorch版本 写在最前面如何检查所有 Conda 环境中的 PyTorch 版本(并重点提示 PyTorch 1.7.1 版本)1. 列出所有 Conda 环境2. 检查每个环境中的 PyTorch 版本方…...
C语言运算符和表达式
1.C语言赋值运算符实例讲解 C 使用运算符(operator)来代表算术运算。例如,运算符可以使它两侧的值加在一起。如果您觉得术语“运算符”听起来比较奇怪,那么请您记住那些东西总得有个名称。与其被称之为“那些东西”或“数学符号”,被称之为“…...
RetinaNet 分类头和回归头的网络结构分析
RetinaNet 是由 Facebook AI Research(FAIR)在 2017 年提出的一种高效的一阶段(one-stage)目标检测算法。相比于两阶段(two-stage)方法,RetinaNet 通过引入 Focal Loss 解决了类别不平衡问题&am…...
app测试有哪些内容?广东深圳软件测试机构推荐
随着智能手机的普及,手机应用app越来越多,因此,企业为了更好的保证用户留存率,开发完app之后必须进行app测试。一个成功的app,软件测试是必不可少的一步,那么app测试需要进行哪些测试内容呢?深圳又有哪些靠…...
新乡医学院第一附属医院启动巨额医疗设备整体维保招标
鉴于项目本身金额巨大,又恰逢省委巡视组进驻期间,该项目备受瞩目,在业内和省内医疗圈引起了极大轰动。全国影响力最大、实力最强的企业全部参与其中,民营企业上海柯渡医疗、上海昆亚医疗以其创新的服务模式和高效的管理机制备受关注;央企通用技术集团凯思轩达医疗科技凭借雄厚的…...
Linux——综合实用操作
目录 IP与主机 ping命令 wget命令 curl命令 端口:设备与外界通讯交流的出入口 进程管理 Linux top命令Windows 任务管理器 磁盘信息监控 df iostat 网络状态监控 sar -n DEV命令 环境变量 上传,下载 压缩 解压tar,zipÿ…...
一个Idea:爆改 T480
爆改 T480 准备大改 T480,家里有一台闲置很久的 T480,不舍得扔,打算升级一下。看了几位up主的视频后,决定动手改造。 计划如下 网卡:加装4G网卡硬盘:更换为 1T 的 NVMe 2280 固态硬盘内存:升…...
网络编程(21)——通过beast库快速实现http服务器
目录 二十一、day21 1. 头文件和作用域重命名 2. reponse时调用的一些函数 3. http_connection a. 构造函数 b. start() c. process_request() d. create_response() e. create_post_response() f. write_response() 4. Server 5. 主函数 6. 测试 1)测…...
Logback
Logback 简介 SpringBoot 内置日志框架 用来自定义控制台日志输出样式、生成日志文件 使用 由于是内置所以不需要引入,稍加配置就可以直接使用。 内置源头查看 配置application.yml # 日志配置 logging:level:com.ruoyi: logging.levelorg.springframework: war…...
Sub - Adjacent Transformer — 对AT的有趣改进
出处:IJCAI 2024 未开源,链接貌似是:jackyue1994/Sub-Adjacent-Transformer (github.com) 贡献:1. 提出:基于 “次邻域” 及 “注意力贡献” 的注意力学习机制,以增强异常、正常的区分;2. 首次…...
『Mysql集群』Mysql高可用集群之主从复制 (一)
Mysql主从复制模式 主从复制有一主一从、主主复制、一主多从、多主一从等多种模式. 我们可以根据它们的优缺点选择适合自身企业情况的主从复制模式进行搭建 . 一主一从 主主复制 (互为主从模式): 实现Mysql多活部署 一主多从: 提高整个集群的读能力 多主一从: 提高整个集群的…...
RK3566 Android11 录音难题:手把手教你搞定ES7202 PDM ADC配置(附驱动修复)
RK3566 Android11音频驱动实战:ES7202 PDM ADC配置与异常修复全解析 当RK3566遇上ES7202这颗纯ADC芯片,不少开发者会在Android11音频子系统中遭遇"无声惊魂"。不同于常规I2S架构,PDM直连方案在驱动层埋着几个关键"暗坑"。…...
手把手教你用SRIO IP核实现FPGA与DSP间高速数据互传:基于AXI-Stream接口的实战
基于SRIO IP核的FPGA与DSP高速数据互传实战指南 在异构计算系统中,FPGA与DSP的高效协同已成为雷达信号处理、无线通信基带处理等领域的核心技术需求。传统的数据传输方式如SPI、UART等已无法满足现代系统对带宽和实时性的严苛要求,而Serial RapidIO&…...
告别论文格式内耗!从标题层级到参考文献,这款工具一键搞定全流程合规排版
在学位论文撰写中,标题层级混乱、页眉页脚错位、参考文献格式不统一、图表排版杂乱是贯穿全文的高频痛点,堪称学术写作的 “格式重灾区”。传统 Word/WPS 依赖手动刷样式、调格式,耗时数小时还易反复出错;LaTeX 门槛高、中文适配差…...
Linux内核链表安全遍历:list_for_each_entry_safe 深度解析
1. 为什么需要安全的链表遍历 在Linux内核开发中,链表是最基础也是最常用的数据结构之一。内核开发者经常需要遍历链表来访问或操作其中的节点。但有一个场景特别棘手:当你需要在遍历过程中删除当前节点时,普通的遍历方法会导致链表断裂甚至系…...
weixin273基于微信小程序的刷题系统的设计与实现+springboot(文档+源码)_kaic
第4章 系统实现4.1登录功能模块的实现登录功能包括用户登录和管理员登录,在登录界面设计中包括用户名和密码、身份的检验。用户名和密码、身份的检验过程由数据库自动完成,此过程需要1秒左右。首先由用户填写账号和密码,然后选择身份…...
使用 C++ 模拟 ShaderLanguage 的 swizzle
经常编写着色器的同学应该对 swizzle(重排)语法非常熟悉,方便又灵活,可以说是用过一次便回味无穷。 代码 vec4 color vec4(1.0, 0.5, 0.0, 1.0); vec3 rgb color.rgb; // { 1.0, 0.5, 0.0 } vec2 xy color.xy; …...
Balena Etcher:三步完成系统镜像烧录,告别复杂命令的困扰
Balena Etcher:三步完成系统镜像烧录,告别复杂命令的困扰 【免费下载链接】etcher Flash OS images to SD cards & USB drives, safely and easily. 项目地址: https://gitcode.com/GitHub_Trending/et/etcher 你是否曾经因为需要制作系统启动…...
病床前尽孝心,脊柱 “被折得濒临损伤”!
长期弯腰照顾卧床病人、喂饭、翻身、擦洗,颈腰椎损伤风险显著。弯腰时腰椎弯曲角度过大,椎间盘承受压力剧增;反复弯腰起身照顾病人,肌肉与椎间盘反复冲击;低头专注护理时,颈椎前伸与腰椎受力形成双重负担。…...
攻防世界 misc题GFSJ1129-【您看我还有机会吗?】
1.工具:010editor、VMware(Ubuntu、binwalk)、在线 Brainfuck解密、CTF-Tools、ImageStrike、7zFM 2.解题: 方法一(最初的解法): 下载附件后,我们打开,发现有一张图片,点击后发现要密码,我发现没有任何密码的提示,怀疑是伪加密(由于篇幅较长,我后续会在写一篇…...
Unity坐标系实战解析:从localPosition到Position的层级关系与应用场景
1. 理解Unity中的坐标系基础 在Unity开发中,坐标系系统是构建3D世界的基石。很多新手开发者容易混淆localPosition和Position的概念,导致物体位置控制出现各种"灵异现象"。我们先从一个生活场景来理解:想象你站在客厅里(…...
