Unity UGUI實現無限滾動列表

Demo鏈接???https://download.csdn.net/download/qq_41973169/89364284icon-default.png?t=N7T8http://Unity UGUI無限滾動列表

在游戲開發中,列表視圖是一個常見的UI組件。實現一個高效的列表視圖尤其重要,尤其是在需要展示大量數據時。本文將介紹如何在Unity中實現一個高效的無限滾動列表,包括兩個關鍵腳本:InfiniteScroll 和 ListItem 兩個腳本 話不多說直接上代碼

Unity版本2022.3.X

InfiniteScroll.cs

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using System;public class InfiniteScroll : MonoBehaviour
{public delegate void ItemDelegate(int itemDataIndex, int slotID);public ItemDelegate OnUpdateItemImpl;// 更新Item回調函數public enum ScrollDirection{Vertical,Horizontal}public GameObject itemPrefab;[Header("橫向滑動表示寬度; 縱向滑動表示高度")]public float itemSize;[Header("列表項間距")]public float spacing; // 列表項間距[Header("最大可見列表項數量")]public int maxVisibleItemCount;[Header("滑動方向")]public ScrollDirection scrollDirection = ScrollDirection.Vertical;private ScrollRect _scrollRect;private RectTransform _contentRectTransform;private int _firstVisibleIndex; // 第一個可見列表項的索引private int _lastVisibleIndex; // 最后一個可見列表項的索引private List<GameObject> _itemList; // 列表項對象列表private float _itemTotalSize; // 列表項總尺寸(包括間距)private int _totalItemDataCount; // item總共數據數量private void Awake(){_itemTotalSize = itemSize + spacing;_itemList = new List<GameObject>();_scrollRect = GetComponent<ScrollRect>();_contentRectTransform = _scrollRect.content.GetComponent<RectTransform>();_scrollRect.onValueChanged.AddListener(OnScrollChanged);}public void Init(){for (int i = 0; i < maxVisibleItemCount; i++){int slotID = i + 1;GameObject obj = Instantiate(itemPrefab, _contentRectTransform);ListItem listItem = obj.GetComponent<ListItem>();listItem.Init(this);listItem.SetSlotID(slotID);obj.name = slotID.ToString();SetPivot(obj, _itemTotalSize * i);_itemList.Add(obj);}itemPrefab.SetActive(false);}private void SetPivot(GameObject obj, float position){RectTransform rect = obj.GetComponent<RectTransform>();if (scrollDirection == ScrollDirection.Vertical){rect.pivot = new Vector2(0.5f, 1);rect.anchorMax = new Vector2(0.5f, 1);rect.anchorMin = new Vector2(0.5f, 1);rect.anchoredPosition = new Vector2(0, -position);}else{rect.pivot = new Vector2(0, 0.5f);rect.anchorMax = new Vector2(0, 0.5f);rect.anchorMin = new Vector2(0, 0.5f);rect.anchoredPosition = new Vector2(position, 0);}}private void OnScrollChanged(Vector2 position){if (scrollDirection == ScrollDirection.Vertical){Func<bool> condition1 = () =>{// 如果Content的Y軸坐標大于上面第二個Item 并且最后的下標不是數據的最后一個則表示向下滑動可以更新Itemreturn _contentRectTransform.anchoredPosition.y > (_firstVisibleIndex + 1) * _itemTotalSize && _lastVisibleIndex < _totalItemDataCount - 1;};Func<bool> condition2 = () =>{// 如果Content的Y軸坐標小于上面第一個Item 并且最上面的索引不為0 則表示向上滑動可以更新Itemreturn _contentRectTransform.anchoredPosition.y < _firstVisibleIndex * _itemTotalSize && _firstVisibleIndex > 0;};UpdateItems(condition1, condition2);}else{Func<bool> condition1 = () =>{// 如果Content的X軸坐標大于右邊第二個Item 并且最后的下標不是數據的最后一個則表示向右滑動可以更新Itemreturn Mathf.Abs(_contentRectTransform.anchoredPosition.x) > (_firstVisibleIndex + 1) * _itemTotalSize && _lastVisibleIndex < _totalItemDataCount - 1;};Func<bool> condition2 = () =>{// 如果Content的X軸坐標小于左邊第一個Item 并且最上面的索引不為0 則表示向左滑動可以更新Itemreturn Mathf.Abs(_contentRectTransform.anchoredPosition.x) < _firstVisibleIndex * _itemTotalSize && _firstVisibleIndex > 0;};UpdateItems(condition1, condition2);}}private void UpdateItemUI(GameObject obj, int dataIndex){ListItem listItem = obj.GetComponent<ListItem>();listItem.SetDataIndex(dataIndex);listItem.UpdateUI();}private void UpdateItems(Func<bool> condition1, Func<bool> condition2){while (condition1()){GameObject first = _itemList[0];RectTransform rectTrans = first.GetComponent<RectTransform>();_itemList.RemoveAt(0);_itemList.Add(first);rectTrans.anchoredPosition = scrollDirection == ScrollDirection.Horizontal ?new Vector2((_lastVisibleIndex + 1) * _itemTotalSize, 0) :new Vector2(0, -(_lastVisibleIndex + 1) * _itemTotalSize);_firstVisibleIndex += 1;_lastVisibleIndex += 1;UpdateItemUI(first, _lastVisibleIndex + 1);}while (condition2()){GameObject last = _itemList[_itemList.Count - 1];RectTransform rectTrans = last.GetComponent<RectTransform>();_itemList.RemoveAt(_itemList.Count - 1);_itemList.Insert(0, last);rectTrans.anchoredPosition = scrollDirection == ScrollDirection.Horizontal ? new Vector2((_firstVisibleIndex - 1) * _itemTotalSize, 0) :new Vector2(0, -(_firstVisibleIndex - 1) * _itemTotalSize);_firstVisibleIndex -= 1;_lastVisibleIndex -= 1;UpdateItemUI(last, _firstVisibleIndex + 1);}}public void RefreshList(){_firstVisibleIndex = 0;for (int i = 0; i < _itemList.Count; i++){GameObject obj = _itemList[i];obj.SetActive(i < _totalItemDataCount);if (i < _totalItemDataCount){_lastVisibleIndex = i;UpdateItemUI(obj, i + 1);}}float size = _itemTotalSize * _totalItemDataCount - spacing;if (scrollDirection == ScrollDirection.Vertical){_contentRectTransform.sizeDelta = new Vector2(_contentRectTransform.sizeDelta.x, size);}else{_contentRectTransform.sizeDelta = new Vector2(size, _contentRectTransform.sizeDelta.y);}_contentRectTransform.anchoredPosition = Vector2.zero;}public void SetTotalItemDataCount(int count){_totalItemDataCount = count;}
}

ListItem.cs

using UnityEngine;
using UnityEngine.UI;public class ListItem : MonoBehaviour
{public Text itemText;private InfiniteScroll _infiniteScroll;private int _slotID;private int _dataIndex;public void Init(InfiniteScroll infiniteScroll){_infiniteScroll = infiniteScroll;}public void SetSlotID(int slotID){_slotID = slotID;}public void SetDataIndex(int dataIndex){_dataIndex = dataIndex;}public void UpdateUI(){itemText.text = $"{_dataIndex} SlotID{_slotID}";if (_infiniteScroll.OnUpdateItemImpl != null){_infiniteScroll.OnUpdateItemImpl.Invoke(_dataIndex, _slotID);}else{Debug.LogError("InfiniteScroll.OnUpdateItemImpl == null");}}
}

測試代碼

MyTest.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MyTest : MonoBehaviour
{public InfiniteScroll horizontalInfiniteScroll;public InfiniteScroll verticalInfiniteScroll;void Start(){horizontalInfiniteScroll.Init();verticalInfiniteScroll.Init();horizontalInfiniteScroll.OnUpdateItemImpl = (dataIndex, slotID) =>{Debug.LogError($"horizontalInfiniteScroll dataIndex:{dataIndex}, slotID:{slotID}");};verticalInfiniteScroll.OnUpdateItemImpl = (dataIndex, slotID) =>{Debug.LogError($"verticalInfiniteScroll dataIndex:{dataIndex}, slotID:{slotID}");};horizontalInfiniteScroll.SetTotalItemDataCount(100);verticalInfiniteScroll.SetTotalItemDataCount(100);horizontalInfiniteScroll.RefreshList();verticalInfiniteScroll.RefreshList();}
}

?測試效果

場景樹UI布局?

腳本掛載

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/16981.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/16981.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/16981.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SRM系統在企業采購中的解決方案及系統供應商推薦

供應商關系管理系統&#xff08;Supplier Relationship Management&#xff09;是一種用于管理企業與供應商之間關系的軟件工具。企業通過SRM系統能夠優化采購流程、提高采購效率、減少成本&#xff0c;并增強與供應商的合作關系。本文將探討SRM系統能夠解決的企業采購問題&…

手動操作很麻煩?試試這個自動加好友神器吧!

你是不是也覺得手動逐一輸入號碼或是微信號&#xff0c;再搜索添加很麻煩&#xff1f;試試這個自動加好友神器——個微管理系統&#xff0c;幫助你省去繁瑣的手工操作&#xff0c;節省時間和精力。 首先&#xff0c;在系統上登錄微信號&#xff0c;無論你有多少個微信號&#…

組合慣導串口數據解析

首先是給串口usb以權限&#xff1a; sudo chmod 666 /dev/ttyUSB0但是不能每次啟動都執行一次&#xff0c;所以需要給一個永久的權限指令&#xff1a; sudo gedit /etc/udev/rules.d/70-ttyusb.rulesKERNEL“ttyUSB[0-9]*”, MODE“0666”然后就能讓ttyUSB0-ttyUSB9默認的權限…

2024/5/27 ARMday9SPI實驗八段數碼管顯示

main.c #include "spi.h" extern void printf(const char *fmt, ...); void delay_ms(int ms) {int i,j;for(i 0; i < ms;i)for (j 0; j < 1800; j); } //保存0-9編碼的數組 int num[10] {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0x3E,0xE0,0xFE,0xF6}; int main…

2024年上半年軟件設計師試題及答案(回憶版)--選擇題

基礎知識選擇題 基礎知識選擇題 1,2,3][4,5,6][1,2,3,4,5,6] &#xff08;總&#xff1a;1分&#xff09; &#xff08;注意&#xff1a;括號內的是截止當前題目總分&#xff09; vlan不能隔絕內外網 &#xff08;2分&#xff09; 鏈路層使用交換機&#xff0c;…

智慧樹下做游戲

游戲開發工程師致力于游戲總體設計 &#xff0c;負責游戲開發工具和運營維護工具的設計與開發 &#xff0c;并配合主程序完成游戲架構及各大功能的設計、開發、調試和其他技術支持 就業方向&#xff1a; 一般有客戶端游戲開發和服務器游戲開發 客戶端開發&#xff1a; 主要負…

光伏開發是用什么工具提高效率?

隨著全球對可再生能源的日益重視&#xff0c;光伏產業作為其中的佼佼者&#xff0c;已經取得了長足的發展。然而&#xff0c;如何提高光伏開發的效率&#xff0c;降低成本&#xff0c;成為了業內關注的焦點。本文將探討光伏開發過程中所使用的工具&#xff0c;以及這些工具如何…

【軟件設計師】——11.多媒體

目錄 11.1 多媒體種類和數據壓縮 11.2 音頻 11.3 圖像 11.4 視頻 11.1 多媒體種類和數據壓縮 多媒體種類 感覺媒體&#xff1a;人接觸信息的感覺形式&#xff0c;直接作用于人的感覺器官&#xff0c;使人產生直接感覺的媒體。如視覺、聽覺、觸覺、嗅覺、味覺等 顯示媒體/表…

設計軟件有哪些?建模和造型工具篇(2),渲染100邀請碼1a12

之前介紹了一批建模工具&#xff0c;這次我們繼續介紹。 1、Forest Pack Forest Pack是由iToo Software公司開發的3ds Max插件&#xff0c;專門用于創建大規模自然環境。它提供了豐富的植被和物體庫&#xff0c;用戶可以快速創建樹木、植物、巖石等元素&#xff0c;并將它們分…

STM32HAL(一)外設驅動框架與回調函數應用

前言&#xff1a;這段時間開始學習STM32F4&#xff0c;同時為了以后的便捷性性就開始學HAL庫了 目錄 HAL庫文件 基本文件結構 API命名規則 HAL庫回調函數 HAL_ XXX _MspInit() / _MspDeInit() HAL_PPP_MspInit() HAL_PPP_MspDeInit() HAL_PPP_ProcessCpltCallback HA…

剛上手Java會踩的坑

1. 用號比較的坑 對Integer類型的兩個參數使用號比較是否相等&#xff0c;或者使用String類型的兩個變量進行比較&#xff0c;天真的認為他們是理所應當的。 其實操作只適用于基本數據類型如int , byte, boolean, short, char, long, float, double這些基本數據類型。 其它…

instanceof 關鍵字的作用

instanceof 嚴格來說是 Java 中的一個雙目運算符&#xff0c;用來測試一個對象是否為一個類的實例&#xff0c;用法為&#xff1a; boolean result obj instanceof Class其中 obj 為一個對象&#xff0c;Class 表示一個類或者一個接口&#xff0c;當 obj 為 Class 的對象&…

JavaEE-JPA(相關概念及Spring JPA)

JPA JPA 相關概念 ORM 框架 (Object Relational Mapping) 建立 Java 程序實體類與數據庫表之間的映射關系。使用 ORM 框架進行編程 Java 程序會根據開發者配置&#xff0c;在運行時自動把數據對象持久化到數據庫中&#xff0c;比直接使用 JDBC 編程更為方便和強大。 常見的 …

Android面試題之Kotlin常見集合操作技巧

本文首發于公眾號“AntDream”&#xff0c;歡迎微信搜索“AntDream”或掃描文章底部二維碼關注&#xff0c;和我一起每天進步一點點 list 創建和修改 不可變list,listOf var list listOf("a","d","f") println(list.getOrElse(3){"Unkn…

Kubernetes可視化界面之DashBoard

1.1 DashBoard Kubernetes Dashboard 是 Kubernetes 集群的一個開箱即用的 Web UI&#xff0c;提供了一種圖形化的方式來管理和監視 Kubernetes 集群中的資源。它允許用戶直接在瀏覽器中執行許多常見的 Kubernetes 管理任務&#xff0c;如部署應用、監控應用狀態、執行故障排查…

用循環神經網絡預測股價

循環神經網絡可以用來對時間序列進行預測&#xff0c;之前我們在介紹循環神經網絡RNN,LSTM和GRU的時候都用到了正弦函數預測的例子&#xff0c;其實這個例子就是一個時間序列。而在眾多的時間序列例子中&#xff0c;最普遍的就是股價的預測了&#xff0c;股價序列是一種很明顯的…

鏈表練習題

返回倒數第K個節點 快慢指針 讓快指針先走k步&#xff0c;再使得快指針與慢指針同時走一步&#xff0c;這樣沒有開額外空間&#xff0c;空間復雜度較低。 代碼實現如下&#xff1a; struct ListNode {int val;struct ListNode* next;}; int kthToLast(struct ListNode* head…

第 52 期:MySQL 半同步復制頻繁報錯

社區王牌專欄《一問一實驗&#xff1a;AI 版》全新改版歸來&#xff0c;得到了新老讀者們的關注。其中不乏對 ChatDBA 感興趣的讀者前來咨詢&#xff0c;表達了想試用體驗 ChatDBA 的意愿&#xff0c;對此我們表示感謝 &#x1f91f;。 目前&#xff0c;ChatDBA 還在最后的準備…

el-table實現合并特定列的所有行

el-table實現合并特定列的所有行 示例&#xff1a; 在這里插入圖片描述 const objectSpanMethod ({ row, column, rowIndex, columnIndex }) > {if (columnIndex 5 || columnIndex 7) {// 就是只保留第一行&#xff0c;其他直接不要&#xff0c;然后行數是列表長度if …

2024年03月 Python(一級)真題解析#中國電子學會#全國青少年軟件編程等級考試

Python等級考試(1~6級)全部真題?點這里 一、單選題(共25題,共50分) 第1題 下列哪個命令,可以將2024轉換成’2024’ 呢?( ) A:str(2024) B:int(2024) C:float(2024) D:bool(2024) 答案:A 本題考察的是str() 語句,將數字轉換成字符串用到的是str() 語句。 …