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

之前已经实现过:

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.pswp.cn/diannao/85228.shtml

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

相关文章

【C++】 类和对象(上)

1.类的定义 1.1类的定义格式 • class为定义类的关键字&#xff0c;后跟一个类的名字&#xff0c;{}中为类的主体&#xff0c;注意类定义结束时后⾯分号不能省 略。类体中内容称为类的成员&#xff1a;类中的变量称为类的属性或成员变量;类中的函数称为类的⽅法或 者成员函数。…

Transformer架构详解:从Attention到ChatGPT

Transformer架构详解&#xff1a;从Attention到ChatGPT 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 Transformer架构详解&#xff1a;从Attention到ChatGPT摘要引言一、Attention机制&#xff1a;Transformer的…

Rock9.x(Linux)安装Redis7

&#x1f49a;提醒&#xff1a;1&#xff09;注意权限问题 &#x1f49a; 查是否已经安装了gcc gcc 是C语言编译器&#xff0c;Redis是用C语言开发的&#xff0c;我们需要编译它。 gcc --version如果没有安装gcc&#xff0c;那么我们手动安装 安装GCC sudo dnf -y install…

EasyExcel使用导出模版后设置 CellStyle失效问题解决

EasyExcel使用导出模版后在CellWriteHandler的afterCellDispose方法设置 CellStyle失效问题解决方法 问题描述&#xff1a;excel 模版塞入数据后&#xff0c;需要设置单元格的个性化设置时失效&#xff0c;本文以设置数据格式为例&#xff08;设置列的数据展示时需要加上千分位…

【Day41】

DAY 41 简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 →…

Express教程【002】:Express监听GET和POST请求

文章目录 2、监听post和get请求2.1 监听GET请求2.2 监听POST请求 2、监听post和get请求 创建02-app.js文件。 2.1 监听GET请求 1️⃣通过app.get()方法&#xff0c;可以监听客户端的GET请求&#xff0c;具体的语法格式如下&#xff1a; // 1、导入express const express req…

C# 文件 I/O 操作详解:从基础到高级应用

在软件开发中&#xff0c;文件操作&#xff08;I/O&#xff09;是一项基本且重要的功能。无论是读取配置文件、存储用户数据&#xff0c;还是处理日志文件&#xff0c;C# 都提供了丰富的 API 来高效地进行文件读写操作。本文将全面介绍 C# 中的文件 I/O 操作&#xff0c;涵盖基…

Vue-Router简版手写实现

1. 路由库工程设计 首先&#xff0c;我们需要创建几个核心文件来组织我们的路由库&#xff1a; src/router/index.tsRouterView.tsRouterLink.tsuseRouter.tsinjectionsymbols.tshistory.ts 2. injectionSymbols.ts 定义一些注入符号来在应用中共享状态&#xff1a; import…

Electron-vite【实战】MD 编辑器 -- 文件列表(含右键快捷菜单,重命名文件,删除本地文件,打开本地目录等)

最终效果 页面 src/renderer/src/App.vue <div class"dirPanel"><div class"panelTitle">文件列表</div><div class"searchFileBox"><Icon class"searchFileInputIcon" icon"material-symbols-light:…

Remote Sensing投稿记录(投稿邮箱写错、申请大修延期...)风雨波折投稿路

历时近一个半月&#xff0c;我中啦&#xff01; RS是中科院二区&#xff0c;2023-2024影响因子4.2&#xff0c;五年影响因子4.9。 投稿前特意查了下预警&#xff0c;发现近五年都不在预警名单中&#xff0c;甚至最新中科院SCI分区&#xff08;2025年3月&#xff09;在各小类上…

吉林第三届全国龙舟邀请赛(大安站)激情开赛

龙舟竞渡处,瑞气满湖光。5月31日&#xff0c;金蛇献瑞龙舞九州2025年全国龙舟大联动-中国吉林第三届全国龙舟邀请赛(大安站)“嫩江湾杯”白城市全民健身龙舟赛在吉林大安嫩江湾国家5A级旅游区玉龙湖拉开帷幕。 上午9时&#xff0c;伴随着激昂的音乐&#xff0c;活力四射的青春舞…

华为OD机试真题——通过软盘拷贝文件(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》 华为OD机试真题《通过…

一起学数据结构和算法(二)| 数组(线性结构)

数组&#xff08;Array&#xff09; 数组是最基础的数据结构&#xff0c;在内存中连续存储&#xff0c;支持随机访问。适用于需要频繁按索引访问元素的场景。 简介 数组是一种线性结构&#xff0c;将相同类型的元素存储在连续的内存空间中。每个元素通过其索引值&#xff08;数…

ZYNQ sdk lwip配置UDP组播收发数据

🚀 一、颠覆认知:组播 vs 单播 vs 广播 通信方式目标设备网络负载典型应用场景单播1对1O(n)SSH远程登录广播1对全网O(1)ARP地址解析组播1对N组O(1)视频会议/物联网群控创新价值:在智能工厂中,ZYNQ通过组播同时控制100台AGV小车,比传统单播方案降低92%网络流量! 🔧 二、…

机器学习:欠拟合、过拟合、正则化

本文目录&#xff1a; 一、欠拟合二、过拟合三、拟合问题原因及解决办法四、正则化&#xff1a;尽量减少高次幂特征的影响&#xff08;一&#xff09;L1正则化&#xff08;二&#xff09;L2正则化&#xff08;三&#xff09;L1正则化与L2正则化的对比 五、正好拟合代码&#xf…

Linux命令之ausearch命令

一、命令简介 ausearch 是 Linux 审计系统 (auditd) 中的一个实用工具,用于搜索审计日志中的事件。它是审计框架的重要组成部分,可以帮助系统管理员分析系统活动和安全事件。 二、使用示例 1、安装ausearch命令 Ubuntu系统安装ausearch命令,安装后启动服务。 root@testser…

mac电脑安装nvm

方案一、常规安装 下载安装脚本&#xff1a;在终端中执行以下命令来下载并运行 NVM 的安装脚本3&#xff1a; bash curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.5/install.sh | bash配置环境变量&#xff1a;安装完成后&#xff0c;需要配置环境变量。如…

Excel 操作 转图片,转pdf等

方式一 spire.xls.free&#xff08;没找设置分辨率的方法&#xff09; macOs开发Java GUI程序提示缺少字体问题解决 Spire.XLS&#xff1a;一款Excel处理神器_spire.xls免费版和收费版的区别-CSDN博客 官方文档 Spire.XLS for Java 中文教程 <dependency><groupI…

oracle goldengate实现远程抽取postgresql 到 postgresql的实时同步【绝对无坑版,亲测流程验证】

oracle goldengate实现postgresql 到 postgresql的实时同步 源端&#xff1a;postgresql1 -> postgresql2 流复制主备同步 目标端&#xff1a;postgresql 数据库版本&#xff1a;postgresql 12.14 ogg版本&#xff1a;21.3 架构图&#xff1a; 数据库安装以及流复制主备…

2.从0开始搭建vue项目(node.js,vue3,Ts,ES6)

从“0到跑起来一个 Vue 项目”&#xff0c;重点是各个工具之间的关联关系、职责边界和技术演化脉络。 从你写代码 → 到代码能跑起来 → 再到代码可以部署上线&#xff0c;每一步都有不同的工具参与。 &#x1f63a;&#x1f63a;1. 安装 Node.js —— 万事的根基 Node.js 是…