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.pswp.cn/diannao/14574.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/14574.shtml
英文地址,請注明出處:http://en.pswp.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 …