Unity实现TableView

基于Scrollview封装的TableView,实现对视野外的Cell回收利用,减少创建Cell的开销。

核心逻辑如下:

/***************************************动态使用cell核心逻辑开始
**************************************///计算所有cell的坐标信息
private void CaculateCellPosition()
{int cellsCount = _dataSource.NumberOfCellsInTableView(this);if (cellsCount > 0){_cellsPositionsList.Clear();float currentPos = 0;for (int i = 0; i < cellsCount; i++){_cellsPositionsList.Add(currentPos);float rowSize = _dataSource.TableCellSizeForIndex(this, i);currentPos += rowSize;}_cellsPositionsList.Add(currentPos);}
}//更新内嵌容器的size
private void UpdateContentSize()
{int cellsCount = _dataSource.NumberOfCellsInTableView(this);if (cellsCount > 0){float maxPosition = _cellsPositionsList[cellsCount];if (IsHorizontal){if (maxPosition > TableViewSize.width){InnerContainerSizeDelta = maxPosition - TableViewSize.width;}}else {InnerContainerSizeDelta = maxPosition;}}
}//获取指定位置对应cell的索引
private int GetIndexFromOffset(float offset)
{int index = 0;int maxIdx = _dataSource.NumberOfCellsInTableView(this) - 1;index = this.CaculateIndexFromOffset(offset);if (index != INVALID_INDEX){index = Math.Max(0, index);if (index > maxIdx){index = INVALID_INDEX;}}return index;
}//计算指定位置对应cell的索引
private int CaculateIndexFromOffset(float offset)
{int low = 0;int high = _dataSource.NumberOfCellsInTableView(this) - 1;float search = offset;while (high >= low){int index = low + (high - low) / 2;float cellStart = _cellsPositionsList[index];float cellEnd = _cellsPositionsList[index + 1];if (search >= cellStart && search <= cellEnd){return index;}else if (search < cellStart){high = index - 1;}else{low = index + 1;}}if (low <= 0){return 0;}return INVALID_INDEX;
}//更新视野内cell的显示
private void UpdateCellsShow()
{int countOfItems = _dataSource.NumberOfCellsInTableView(this);if (0 == countOfItems){return;}int startIdx = 0, endIdx = 0, idx = 0, maxIdx = 0;float offset = this.GetContentOffset();maxIdx = Mathf.Max(countOfItems - 1, 0);endIdx = this.GetIndexFromOffset(offset);if (endIdx == INVALID_INDEX){endIdx = countOfItems - 1;}offset -= IsHorizontal ? -TableViewSize.width : this.TableViewSize.height;startIdx = this.GetIndexFromOffset(offset);if (startIdx == -1){startIdx = countOfItems - 1;}if (IsHorizontal){//横向与纵向相反int tmp = startIdx;startIdx = endIdx;endIdx = tmp;}//--_usingCellsList.Sort(new TableViewCellComparer());//--检测可回收的cell--BEGINif (_usingCellsList.Count > 0){var cell = _usingCellsList[0];idx = cell.Index;while (idx < startIdx){this.MoveCellOutOfSight(cell);if (_usingCellsList.Count > 0){cell = _usingCellsList[0];idx = cell.Index;}else{break;}}}if (_usingCellsList.Count > 0){var cell = _usingCellsList[_usingCellsList.Count - 1];idx = cell.Index;while (idx <= maxIdx && idx > endIdx){this.MoveCellOutOfSight(cell);if (_usingCellsList.Count > 0){cell = _usingCellsList[_usingCellsList.Count - 1];idx = cell.Index;}else{break;}}}//--检测可回收的cell--ENDfor (int i = startIdx; i <= endIdx; i++){if (_cellUsingIdxs.Contains(i)){continue;}this.UpdateCellByIndex(i);}
}
//更新指定cell的显示
private void UpdateCellByIndex(int index)
{TableViewCell cell = _dataSource.TableCellAtIndex(this, index);cell.SetIndex(index);cell.ClickEvent.RemoveListener(CellDidClick);cell.ClickEvent.AddListener(CellDidClick);if (cell.gameObject.activeSelf == false){cell.gameObject.SetActive(true);}//--float cellSize = _dataSource.TableCellSizeForIndex(this, index);Vector2 pos = new Vector2();if (IsHorizontal){pos.x = _cellsPositionsList[index] - InnerContainerSizeDelta * 0.5f - 0.5f * TableViewSize.width + cellSize * 0.5f;pos.y = 0;}else {pos.x = 0;pos.y = _cellsPositionsList[index] - InnerContainerSizeDelta * 0.5f + cellSize * 0.5f;}cell.gameObject.GetComponent<RectTransform>().anchoredPosition = pos;//--_usingCellsList.Add(cell);_cellUsingIdxs.Add(cell.Index);
}//回收视野外的cell
private void MoveCellOutOfSight(TableViewCell cell)
{_freedCellsStack.Push(cell);_usingCellsList.Remove(cell);_cellUsingIdxs.Remove(cell.Index);cell.ClickEvent.RemoveListener(CellDidClick);cell.ResetCell();
}/***************************************动态使用cell核心逻辑结束
**************************************/

如何使用呢?按照下面的流程操作即可。

1.创建Test 脚本,脚本继承ITableViewDataSource并实现对应的方法。【ITableViewDelegate根据具体情况决定继承与否】
 public interface ITableViewDataSource{int NumberOfCellsInTableView(TableView tableView);float TableCellSizeForIndex(TableView tableView, int index);TableViewCell TableCellAtIndex(TableView tableView, int index);}
 public class Test : MonoBehaviour, ITableViewDataSource, ITableViewDelegate{public TableView tableView;public GameObject hCell = null;public GameObject vCell = null;void Start(){}public int NumberOfCellsInTableView(TableView tableView){return 20;}public float TableCellSizeForIndex(TableView tableView, int index){return 90;}public TableViewCell TableCellAtIndex(TableView tableView, int index){TableViewCell cell = tableView.ReusableCell();if (cell == null){GameObject obj = Instantiate(tableView.IsHorizontal ? hCell : vCell, tableView.InnerContainerContent().transform);cell = obj.GetComponent<TableViewCell>();}cell.name = "Cell " + index;return cell;}public void TableCellClicked(TableView tableView, int index){Debug.Log("TableViewDidSelectCellForRow : " + index);}}
 2.脚本挂载到载体,并绑定对应的变量【HCell和VCell只是为了方便测试横/纵向滚动】

 3.创建TestCell脚本,并继承TableViewCell
  public class TestCell : TableViewCell{public Text txt;public override void UpdateDisplay(){txt.text = "Index " + Index;}}
 4.将TestCell脚本挂载到Scrollview中显示的预制体上
 5.Test脚本中设置TableView的必要属性,调用ReloadData()接口
void Start()
{tableView.Delegate = this;tableView.DataSource = this;tableView.ReloadData();
}

效果如下:  

u3d-demo

项目地址:https://github.com/jjinglover/UnityTableView

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

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

相关文章

利用java8 的 CompletableFuture 优化 Flink 程序,性能提升 50%

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

flume sink 简介及官方用例

1、HDFS Sink 此sink将事件写入 Hadoop 分布式文件系统 &#xff08;HDFS&#xff09; 中。它目前支持创建文本和序列文件。它支持两种文件类型的压缩。可以根据经过的时间或数据大小或事件数定期滚动文件&#xff08;关闭当前文件并创建一个新文件&#xff09;。它还按事件起…

AI图书推荐:用100个ChatGPT提示词掌握Python编程

《用100个ChatGPT提示词掌握Python编程》&#xff08;ChatGPT:Your Python Coach Mastering the Essentials in 100 Prompts&#xff09; 塞尔吉奥罗哈斯-加莱亚诺&#xff08;Sergio Rojas-Galeano&#xff09;是一位热情的计算机科学家&#xff0c;对人工智能、机器学习、进化…

C++中获取int最大与最小值(补)

上文中&#xff0c;我们学习了C中获取int最大与最小值的两种方法&#xff1a;C库和移位运算&#xff0c;这篇文章将解决在移位运算中遇到的各种报错&#xff0c;并提出一种新的生成int最值的方法 上文链接&#xff1a;http://t.csdnimg.cn/cn7Ad 移位运算取最值常见报错 Dev…

汇编语言(STC89C52)

指令是计算机计算CPU根据人的意图来执行某种操作的命令。一台计算机所执行的全部指令的集合&#xff0c;称为这个CPU的指令系统。而想要使计算机按照人们的要求完成一项工作&#xff0c;就必须让CPU按顺序执行预设的操作&#xff0c;即逐条执行人们编写的指令。这种按照人民要求…

C++ 写的_string类,兼容std::string, MFC CString和 C# 的string

代码例子&#xff1a; using namespace lf; int main() { CString s1 _t("http://www.csdn.net"); _string s2 s1; CString s3 s2; _pcn(s1); _pcn(s2); _pcn(s3); return 0; } 输出&#xff1a; _Str.h /***************************************…

网创教程:WordPress插件网创自动采集并发布

网创教程&#xff1a;WordPress插件网创自动采集并发布 使用插件注意事项&#xff1a; 如果遇到404错误&#xff0c;请先检查并调整网站的伪静态设置&#xff0c;这是最常见的问题。需要定制化服务&#xff0c;请随时联系我。 本次更新内容 我们进行了多项更新和优化&#x…

深入解析kube-scheduler的算法自定义插件

目录 ​编辑 一、问题引入 二、自定义步骤 三、最佳实践考虑 一、问题引入 当涉及到 Kubernetes 集群的调度和资源分配时&#xff0c;kube-scheduler 是一个关键组件。kube-scheduler 负责根据集群的调度策略&#xff0c;将 Pod 分配到适当的节点上。kube-scheduler 默认使…

python爬虫学习代码1

百度翻译&#xff1a;利用爬虫技术模拟人工查询英文单词&#xff0c;将查到的信息保存到本地 import requests import json # 1.指定url post_url https://fanyi.baidu.com/sug # 2.UA标识 headers {"User-Agent": Mozilla/5.0 (Windows NT 10.0; Win64; x64) Appl…

pyqt6入门案例

效果预览 hello.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0"><class>Dialog</class><widget class"QDialog" name"Dialog"><property name"geometry"><…

android studio接入facebook踩坑1

今天在接入facebook第三方登录的时候&#xff0c;点击登录按钮&#xff0c;APP闪退&#xff0c;并报错 java.lang.RuntimeException Failure delivering result ResultInfo{whonull,request64206,result-1} 新文章链接https://lengmo714.top/facebook1.html 如下图&#xff1a;…

OpenGL学习入门及开发环境搭建

最近学习OpenGL开发&#xff0c;被各种openGL库搞得晕头转向&#xff0c;什么glut, glew glfw glad等等。 可以参考这边博客:OpenGL 下面的 glut freeglut glfw 都是个啥_glx wgl的中文-CSDN博客 glfw是glut的升级版&#xff0c;跨平台的主要处理窗口 事件相关。 glad是glew…

React项目知识积累(四)

1.useMemo( ) 在 React 中&#xff0c;useMemo 是一个 Hook&#xff0c;用于记忆计算结果&#xff0c;只有当依赖项之一发生变化时&#xff0c;才会重新计算。这有助于避免不必要的计算和渲染&#xff0c;从而提高应用程序的性能。 基本语法如下&#xff1a; const memoized…

html多节点生成图片并导出zip包

html多节点生成图片并导出zip包 背景 在做项目时遇到一个要将html节点展示的图片列表统一导出为zip包的需求。 难点 将html节点生成图片将多张图片加入zip包中&#xff0c;然后下载 解决html生成图片问题 参考html截图的思路使用 pnpm add html-to-image如何将图片资源生成z…

鸿蒙OS开发:【一次开发,多端部署】(多设备自适应能力)简单介绍

多设备自适应能力 介绍 本示例是《一次开发&#xff0c;多端部署》的配套示例代码&#xff0c;展示了[页面开发的一多能力]&#xff0c;包括自适应布局、响应式布局、典型布局场景以及资源文件使用。 名称简介 开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhe…

数据可视化技术头歌测试合集

努力是为了不平庸~ 学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰 目录 时间趋势可视化-柱形图 第1关&#xff1a;“大胃王”比赛数据柱形图绘制——绘制柱形图的基本步骤 任务描述 相关知识 观察和处理数据 绘…

Linux中gcc/g++的基本使用

目录 gcc/g的使用gcc/g是如何生成可执行文件的预处理编译汇编链接 库.o文件是如何与库链接的&#xff1f; debug版本和release版本 gcc/g的使用 在windows中&#xff0c;我们在VS中编写好了代码之后就可以直接在VS中对源码进行编译等操作后运行 而在Linux下&#xff0c;我们可…

LeetCode 279 —— 完全平方数

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 此图利用动态规划进行求解&#xff0c;首先&#xff0c;我们求出小于 n n n 的所有完全平方数&#xff0c;存放在数组 squareNums 中。 定义 dp[n] 为和为 n n n 的完全平方数的最小数量&#xff0c;那么有状态…

vue 展示svg矢量图可缩放拖动

使用插件&#xff1a;svg-pan-zoom <template> <!-- svg图--><div id"svgContainer"></div> </template><script> import svgPanZoom from svg-pan-zoom import svgFile from ../datav/img/220kVscb.svg // 路径根据实际情况调…

MySQL存储过程实现累加运算 1+2+…+n 等于多少?

MySQL创建存储过程&#xff0c;实现累加运算&#xff0c;计算 12…n 等于多少。具体的代码如下 1、实现计算123…n的和 DELIMITER // CREATE PROCEDURE sp_add_sum_num(IN n INT) BEGIN DECLARE i INT; DECLARE sum INT; SET i 1; SET sum 0;WHILE i < n DO SET sum …