Unity 中实现首尾无限循环的 ListView

news2025/6/2 7:37:19

之前已经实现过:

Unity 中实现可复用的 ListView-CSDN博客文章浏览阅读5.6k次,点赞2次,收藏27次。源码已放入我的 github,地址:Unity-ListView前言实现一个列表组件,表现方面最核心的部分就是重写布局(Layout)。对于简单的列表,尤其是“Cell数量固定且较少、没有超页滚动展示”一类的需求,使用UGUI自带的布局组件进行布局即可。分别为:水平布局组件(Horizontal Layout Group)、竖直布局组件(Vertical Layout Gro..._unity listview https://blog.csdn.net/NRatel/article/details/100561203Unity 中实现可复用的 GridView-CSDN博客文章浏览阅读4k次。本文介绍了如何基于Unity的UGUI系统设计一个灵活的GridView组件。作者分析了GridLayoutGroup的参数,讨论了StartCorner和StartAxis的排布方式、Constraint的灵活性以及Padding与对齐方式的巧妙结合。在实现过程中,修改了ScrollRect的关联ScrollBar和布局接口,设计了适应不同滑动方向的布局,并实现了元素复用逻辑,包括四种滑动方向的计算。此外,还探讨了Content锚点、行列约束和对齐方式的调整,以提高组件的易用性。 https://blog.csdn.net/NRatel/article/details/124063559首尾无限循环 的列表,还是以 ListView 为基础。

在此之前,先参照 GrideView 修改 ListView:

使其 继承 UIScrollRect(原因是必须修改部分源码)

并支持参数:

1、MovementAxis :
        横向滑动 或 竖向滑动。

2、StartSide :
        横向滑动时,可选 元素的排列方向:从左往右 或 从右往左;
        竖向滑动时,可选 元素的排列方向:从上往下 或 从下往上。

3、ChildAligment :
        横向滑动时,可选 元素的上下对齐方式:居上/居中/居下;
        竖向滑动时,可选 元素的左右对齐方式:居左/居中/居右。

----------------------------------------- NRatel割 -----------------------------------------

Loop 首尾循环的改动要点:
(以下仅以 MovementAxis=Horizontal,StartSide=Left 的情形阐述)

先看这种情况:核心内容宽度 > viewport 宽度

1、使 Content 在移动时,非原核心内容区也能够显示 0~Count-1 范围内的 Cell元素,让越界索引不要提前retrun,而是在显示时转到 0~Count-1 之中。

如图:黑色区域为 Content, 当其继续往右滑动时,进入Viewport、但已超出 Content 的部分,仍能生成越界元素,并能将越界索引转到 界内索引之中。

需要修改 CalcIndexes,使其不要立刻拦截越界索引。而是在 DisAppearCells 和 AppearCells 时,根据 索引值判断是否越界,抽出两个方法:

//是否有效索引(只将显示索引显示到列表中,默认为 0~cellCount 之间)
//loop时,认为任意索引都是有效的,以使非 0~cellCount 的区域能够显示元素,之后再在 ConvertIndexToValid 转换
protected virtual bool IsValidIndex(int index)
{
    if (m_Loop) { return true; }
    else { return index >= 0 && index < m_CellCount; }
}
//转换索引至有效(默认无需处理)
//loop时,将任意索引数转到 [0~cellCount-1] 中
protected virtual int ConvertIndexToValid(int index)
{
    if (m_Loop) { return (index % m_CellCount + m_CellCount) % m_CellCount; }
    else { return index; }
}

处理完本条之后,理论上,将 Content的宽度设为 无限大,就可以直接支持首尾无限循环。
不过,最好还是选择位置重置的方案。

2、滑动时,从初始位置开始,只要向左/向右滑出超过1个重置单位,就将 Content 重置回起始位置。
(注意,滑动过程,完全无需考虑Cell显示问题,完全由①处理,可将Content想象为一张整图)
(注意这里说的 1个重置单位 = 1核心内容宽度 + 1个spacingX)

3、将 Content 宽度扩为原核心内容宽度扩展的N倍,使其满足位置重置的基本条件。

        支持从初始位置开始,向左向右各滑动1个重置单位,需要在两侧至少各扩展出1个重置单位。
        但为了避免 翻超1个重置单位触及边缘 触发回弹,可以额外多出1或2个重置单位。
        注意,扩宽 Content 更多倍是毫无成本的!这里只是思考至少应该扩展几倍。
        所以,直接定为 2+2=4倍。

4、再回头来思考 核心内容宽度 < viewport宽度 的倍数

        在上面的基础上,只需简单处理:将 核心内容宽度 先翻倍,使超过 viewport宽度。
        注意,这种情况下,在Viewport中会出现多个同一Cell,属于正常现象。

5、重置Content位置。但小心不能影响到 ScrollRect 内部的 速度值计算!!!

        我用了不少时间才解决这个问题。

        位置的重置,不能放在 OnScrollValueChanged。原因是:

        ①、ScrollRect 的 LateUpdate中,有逻辑为:
        开启惯性速度选项,进行拖拽时,会根据Content相邻两帧的 位置确定后续的 惯性起始速度。

        因此,如果在滑动过程中,如果只突然修改 Content 位置,将会导致 速度剧变

        ②、在 OnScrollValueChanged 修改 Content 位置过晚,将使 其他注册 OnScrollValueChanged 的地方无法获取的真实 value。

        因此,可在 SetContentAnchoredPosition 方法中,增加一个虚方法,供子类重写修改Content 的位置。

        在具体修改Content位置时,还需注意:

        ①、要同时更新 m_PrevPosition,以使本帧 LateUpdate中 计算的 m_Velocity 不会因位置剧变而剧变。

        ②、要同时更新 m_ContentStartPosition,以使 OnDrag 中,Content位置跟随鼠标移动时,不反复触发此“位置超过一页的重置逻辑”,否则下一帧 m_PrevPosition 又将执行一次偏移(上一行代码),还是会导致速度剧变。

//Content初始位置
float contentStartPosX = -m_CellStartOffsetOnMovementAxis;
//获取当前位置
float curContentPosX = m_Content.anchoredPosition.x;
//Content向左时,Content重置点坐标(初始位置左侧1个重置宽度)
float leftResetPosX = contentStartPosX - m_LoopResetSizeOnMovementAxis;
//Content向右时,Content重置点坐标(初始位置右侧1个重置宽度)
float rightResetPosX = contentStartPosX + m_LoopResetSizeOnMovementAxis;
if (curContentPosX < leftResetPosX)
{
    m_Content.anchoredPosition += Vector2.right * m_LoopResetSizeOnMovementAxis;
    //更新,以使本帧 LateUpdate中 计算的 m_Velocity 不会因位置剧变而剧变
    m_PrevPosition += Vector2.right * m_LoopResetSizeOnMovementAxis;
    //更新,以使 OnDrag 中,Content位置跟随鼠标移动时,不反复触发此“位置超过一页的重置逻辑”,否则下一帧m_PrevPosition又将执行一次偏移(上一行代码),还是会导致速度剧变
    m_ContentStartPosition += Vector2.right * m_LoopResetSizeOnMovementAxis;
}
else if (curContentPosX > rightResetPosX)
{
    m_Content.anchoredPosition += Vector2.left * m_LoopResetSizeOnMovementAxis;
    //更新,以使本帧 LateUpdate中 计算的 m_Velocity 不会因位置剧变而剧变
    m_PrevPosition += Vector2.left * m_LoopResetSizeOnMovementAxis;
    //更新,以使 OnDrag 中,Content位置跟随鼠标移动时,不反复触发此“位置超过一页的重置逻辑”,否则下一帧m_PrevPosition又将执行一次偏移(上一行代码),还是会导致速度剧变
    m_ContentStartPosition += Vector2.left * m_LoopResetSizeOnMovementAxis;
}

----------------------------------------- NRatel割 -----------------------------------------

实现效果:

源码:

https://github.com/NRatel/Unity-ListViewhttps://github.com/NRatel/Unity-ListView

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

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

相关文章

mongodb集群之副本集

目录 1. 适用场景备份高可用性 2. 集群搭建如何搭建资源规划根据资源完成各节点conf文件的配置启动各个mongodb节点初始化集群信息 搭建实例Linux搭建实例&#xff08;待定&#xff09;Windows搭建实例 3. 副本集基础操作4.集群平滑升级 1. 适用场景 备份 1&#xff09;服务器…

基于微服务架构的社交学习平台WEB系统的设计与实现

设计&#xff08;论文&#xff09;题目 基于微服务架构的社交学习平台WEB系统的设计与实现 摘 要 社交学习平台 web 系统要为学习者打造一个开放、互动且社交性强的在线教育环境&#xff0c;打算采用微服务架构来设计并实现一个社交学习平台 web 系统&#xff0c;以此适应学…

放假带出门的充电宝买哪种好用耐用?倍思超能充35W了解一下!

端午节的到来和毕业季的临近&#xff0c;让很多人开始计划出游或长途旅行。而在旅途中&#xff0c;一款好用耐用的充电宝可以省不少事。今天&#xff0c;我们就来聊聊放假带出门的充电宝买哪种好用耐用&#xff0c;看看为什么倍思超能充35W更适合带出门~ 一、为什么需要一款好用…

AI智能体策略FunctionCalling和ReAct有什么区别?

Dify 内置了两种 Agent 策略&#xff1a;Function Calling 和 ReAct&#xff0c;但二者有什么区别呢&#xff1f;在使用时又该如何选择呢&#xff1f;接下来我们一起来看。 1.Function Calling Function Call 会通过将用户指令映射到预定义函数或工具&#xff0c;LLM 先识别用…

改进自己的图片 app

1. 起因&#xff0c; 目的: 前面我写过一个图片 app &#xff0c; 最新做了些改动。 把原来的一列&#xff0c;改为3列&#xff0c; 继续使用瀑布流手机上使用&#xff0c;更流畅&#xff0c;横屏显示为2列。 2. 先看效果 3. 过程: 过程太细碎了&#xff0c;这里只是做一下…

Uniapp+UView+Uni-star打包小程序极简方案

一、减少主包体积 主包污染源&#xff08;全局文件依赖&#xff09;劲量独立导入 componentsstaticmain.jsApp.vueuni.css 分包配置缺陷&#xff0c;未配置manifest.json中mp-weixin节点 "usingComponents" : true,"lazyCodeLoading" : "requiredC…

算法题(159):快速幂

审题&#xff1a; 本题需要我们计算出(a^b)%c的值&#xff0c;并按照规定格式输出 思路&#xff1a; 方法一&#xff1a;暴力解法 我们直接循环b次计算出a^b,然后再取余c&#xff0c;从而得出最终结果 时间上&#xff1a;会进行2^31次&#xff0c;他的数量级非常大&#xff0c;…

【新品发布】嵌入式人工智能实验箱EDU-AIoT ELF 2正式发布

在万物互联的智能化时代&#xff0c;将AI算法深度植入硬件终端的技术&#xff0c;正悄然改变着工业物联网、智慧交通、智慧医疗等领域的创新边界。为了助力嵌入式人工智能在教育领域实现高质量发展&#xff0c;飞凌嵌入式旗下教育品牌ElfBoard&#xff0c;特别推出嵌入式人工智…

基于javaweb的SpringBoot体检管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

IPD的基础理论与框架——(四)矩阵型组织:打破部门壁垒,构建高效协同的底层

在传统的组织架构中&#xff0c;企业多采用直线职能制&#xff0c;就像一座等级森严的金字塔&#xff0c;信息沿着垂直的层级传递&#xff0c;员工被划分到各个职能部门。这种架构职责清晰、分工明确&#xff0c;在稳定的市场环境中&#xff0c;能让企业高效运作&#xff0c;发…

小程序为什么要安装SSL安全证书

小程序需要部署SSL安全证书&#xff0c;这是小程序开发及运营的强制性要求&#xff0c;也是保障用户数据安全、提升用户体验和满足平台规范的必要措施。 一、平台强制要求 微信小程序官方规范 微信小程序明确要求所有网络请求必须通过HTTPS协议传输&#xff0c;服务器域名需配…

python打卡训练营打卡记录day40

知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 作业&#xff1a;仔细学习下测试和训练代码…

【清晰教程】利用Git工具将本地项目push上传至GitHub仓库中

Git 是一个分布式版本控制系统&#xff0c;由 Linus Torvalds 创建&#xff0c;用于有效、高速地处理从小到大的项目版本管理。GitHub 是一个基于 Git 的代码托管平台&#xff0c;提供了额外的协作和社交功能&#xff0c;使项目管理更加高效。它们为项目代码管理、团队协作和持…

20250529-C#知识:静态类、静态构造函数和拓展方法

C#知识&#xff1a;静态类、静态构造函数和拓展方法 静态类一般用来编写工具类 1、静态类 用static关键字修饰的类一般充当工具类只能包含静态成员,不能包含静态索引器不能被实例化静态方法只能使用静态成员非静态方法既可以使用非静态成员&#xff0c;也可以使用静态成员 sta…

实验设计与分析(第6版,Montgomery)第4章随机化区组,拉丁方, 及有关设计4.5节思考题4.18~4.19 R语言解题

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅珏生译) 第章随机化区组&#xff0c;拉丁方&#xff0c; 及有关设计4.5节思考题4.18~4.19 R语言解题。主要涉及方差分析&#xff0c;拉丁方。 batch <- c(rep("batch1",5), rep(&quo…

【吾爱】逆向实战crackme160学习记录(一)

前言 最近想拿吾爱上的crackme程序练练手&#xff0c;发现论坛上已经有pk8900总结好的160个crackme&#xff0c;非常方便&#xff0c;而且有很多厉害的前辈已经写好经验贴和方法了&#xff0c;我这里只是做一下自己练习的记录&#xff0c;欢迎讨论学习&#xff0c;感谢吾爱论坛…

vue2 + webpack 老项目升级 node v22 + vite + vue2 实战全记录

前言 随着这些年前端技术的飞速发展&#xff0c;几年前的一些老项目在最新的环境下很可能会出现烂掉的情况。如果项目不需要升级&#xff0c;只需要把编译后的文件放在那里跑而不用管的话还好。但是&#xff0c;某一天产品跑过来给你讲要升级某一个功能&#xff0c;你不得不去…

STM32的HAL编码流程总结(上部)

目录 一、GPIO二、中断系统三、USART串口通信四、I2C通信五、定时器 一、GPIO 1.选择调试类型 在SYS中Debug选择Serial Wire模式 2.选择时钟源 在RCC中将HSE和LSH都选择为内部晶振 3.时钟树配置 4.GPIO配置 在芯片图上选择开启的引脚和其功能 配置引脚的各自属性 5.工…

深度学习|pytorch基本运算

【1】引言 pytorch是深度学习常用的包&#xff0c;顾名思义&#xff0c;就是python适用的torch包&#xff0c;在python里面使用时直接import torch就可以调用。 需要注意的是&#xff0c;pytorch包与电脑配置、python版本有很大关系&#xff0c;一定要仔细阅读安装要求、找到…

替代 WPS 的新思路?快速将 Word 转为图片 PDF

在这个数字化办公日益普及的时代&#xff0c;越来越多的人开始关注文档处理工具的功能与体验。当我们习惯了某些便捷操作时&#xff0c;却发现一些常用功能正逐渐变为付费项目——比如 WPS 中的一项实用功能也开始收费了。 这款工具最特别的地方在于&#xff0c;可以直接把 W…