当前位置:网站首页>Application example of infinite list [uigridview]
Application example of infinite list [uigridview]
2022-07-07 15:52:00 【Le_ Sam】
UIGridView Source code
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//Introduction: Infinite list
//Content Mount forbidden on ContentSizeFilter and LayOutGroup And so on
[DisallowMultipleComponent]
[RequireComponent(typeof(ScrollRect))]
public class UIGridView : MonoBehaviour
{
private Action<Transform, int> _handle;
public enum Arrangement
{
Horizontal = 0,
Vertical,
}
public enum HorizontalAlign
{
Left,
Middle,
Right,
}
public enum VerticalAlign
{
Top,
Middle,
Bottom,
}
public Arrangement arrangement = Arrangement.Vertical;
// It is useful when choosing horizontal or vertical flow , Refers to each line / Maximum number of columns
public int MaxPerLine
{
get { return maxPerLine; }
set { SetMaxPerLine(value); }
}
public HorizontalAlign horizontalAlign = HorizontalAlign.Left;
public VerticalAlign verticalAlign = VerticalAlign.Top;
public Vector2 viewPort;
public float rowSpace = 0;
public float columuSpace = 0;
public float marginTop = 0;
public float marginBottom = 0;
public float marginLeft = 0;
public float marginRight = 0;
public int maxPerLine;
public int childCount; // The total number of data to be rendered
public GameObject item;
public GameObject Child
{
get { return item; }
set { SetItem(value); }
}
public int ChildCount
{
get { return childCount; }
set { SetChildCount(value, true); }
}
public Vector2 ViewPort
{
get { return viewPort; }
set { SetViewPort(value); }
}
ScrollRect scrollRect;
RectTransform content;
Vector2 itemSize;
List<Transform> items;
Dictionary<int, int> contains;
List<int> outOfContains;
int scrollLineIndex; // Current first element index
int totalCount; // stay UI The number shown in ( Not multiplied by maxPerLine)
Vector2 startPos; // Where the first element is located
int startIndex; // Current rendering start coordinates
int endIndex; // Current rendering end coordinates
void Start()
{
maxPerLine = maxPerLine == 0 ? 1 : maxPerLine;
items = new List<Transform>();
contains = new Dictionary<int, int>();
outOfContains = new List<int>();
scrollRect = transform.GetComponent<ScrollRect>();
content = scrollRect.content;
if (content == null)
{
Debug.Log("ScrollRect " + scrollRect.gameObject.name + " Has No Content, Please Check And Retry.");
return;
}
//viewPort = scrollRect.viewport.rect.size;
if (item != null)
SetItem(item);
content.anchorMax = new Vector2(0, 1);
content.anchorMin = new Vector2(0, 1);
content.pivot = new Vector2(0, 1);
ReBuild();
}
public void ReBuild()
{
if (scrollRect == null || content == null || item == null) return;
ResetChildren();
Vector2 maskSize = viewPort;
int count = 0;
if (arrangement == Arrangement.Horizontal)
{
count = Mathf.CeilToInt(maskSize.x / itemSize.x) + 1; // Number of horizontal columns
startPos = Vector2.zero;
startPos.x = marginLeft;
if (verticalAlign == VerticalAlign.Top)
{
startPos.y = -marginTop;
}
else if (verticalAlign == VerticalAlign.Middle)
{
startPos.y = -(maskSize.y * 0.5f - (itemSize.y * maxPerLine + (maxPerLine - 1) * rowSpace) * 0.5f);
}
else if (verticalAlign == VerticalAlign.Bottom)
{
startPos.y = -(maskSize.y - marginBottom - itemSize.y * maxPerLine - rowSpace * (maxPerLine - 1));
}
}
else if (arrangement == Arrangement.Vertical)
{
count = Mathf.CeilToInt(maskSize.y / itemSize.y) + 1; // Number of vertical rows
startPos = Vector2.zero;
startPos.y = -marginTop; // Reset the start node position
if (horizontalAlign == HorizontalAlign.Left)
{
startPos.x = marginLeft;
}
else if (horizontalAlign == HorizontalAlign.Middle)
{
startPos.x = (maskSize.x * 0.5f - (itemSize.x * maxPerLine + (maxPerLine - 1) * columuSpace) * 0.5f);
}
else if (horizontalAlign == HorizontalAlign.Right)
{
startPos.x = maskSize.x - marginRight - itemSize.x * maxPerLine - columuSpace * (maxPerLine - 1);
}
}
totalCount = count;
SetChildCount(childCount, true);
BackTop();
scrollRect.onValueChanged.RemoveAllListeners();
scrollRect.onValueChanged.AddListener(OnValueChanged);
}
// List scrolling
private void OnValueChanged(Vector2 vec)
{
switch (arrangement)
{
case Arrangement.Horizontal:
vec.x = Mathf.Clamp(vec.x, 0, 1);
break;
case Arrangement.Vertical:
vec.y = Mathf.Clamp(vec.y, 0, 1);
break;
}
int curLineIndex = GetCurLineIndex();
if (curLineIndex != scrollLineIndex)
UpdateRectItem(curLineIndex, false);
}
private int GetCurLineIndex()
{
switch (arrangement)
{
case Arrangement.Horizontal:
return
Mathf.FloorToInt(Mathf.Abs(content.anchoredPosition.x < 0.1f ? content.anchoredPosition.x : 0.1f - marginLeft) /
(columuSpace + itemSize.x));
case Arrangement.Vertical:
return
Mathf.FloorToInt(Mathf.Abs(content.anchoredPosition.y > -0.1f ? content.anchoredPosition.y : -0.1f - marginTop) /
(rowSpace + itemSize.y));
}
return 0;
}
private void UpdateRectItem(int curLineIndex, bool forceRender)
{
if (curLineIndex < 0)
return;
startIndex = curLineIndex * maxPerLine;
endIndex = (curLineIndex + totalCount) * maxPerLine;
if (endIndex >= childCount)
endIndex = childCount;
contains.Clear(); // Render sequence number
outOfContains.Clear(); //items The index of
for (int i = 0; i < items.Count; i++)// If currently rendered item Contained in the
{
int index = int.Parse(items[i].gameObject.name);
if (index < startIndex || index >= endIndex)
{
outOfContains.Add(i);
items[i].gameObject.SetActive(false);
}
else
{
items[i].gameObject.SetActive(true);
contains.Add(index, i);
}
}
// ************* Change rendering ****************
for (int i = startIndex; i < endIndex; i++)
{
if (!contains.ContainsKey(i))
{
Transform child = items[outOfContains[0]];
outOfContains.RemoveAt(0);
child.gameObject.SetActive(true);
int row = i / maxPerLine;
int col = i % maxPerLine;
if (arrangement == Arrangement.Vertical)
child.localPosition = startPos +
new Vector2(col * itemSize.x + (col) * columuSpace,
-row * itemSize.y - (row) * rowSpace);
else
child.localPosition = startPos +
new Vector2(row * itemSize.x + (row) * columuSpace,
-col * itemSize.y - (col) * rowSpace);
child.gameObject.name = i.ToString();
if (_handle != null)
_handle(child, i);
}
else if (forceRender)
{
if (_handle != null)
_handle(items[contains[i]], i);
}
}
scrollLineIndex = curLineIndex;
}
/// Remove all current
private void ResetChildren()
{
items.Clear();
for (int i = 0; i < content.childCount; i++)
{
Transform child = content.GetChild(i);
child.gameObject.SetActive(false);
}
}
// Create a new node
private RectTransform CreateItem(int index)
{
Transform child;
if (content.childCount > index)
{
child = content.GetChild(index);
}
else
{
GameObject obj = GameObject.Instantiate(item) as GameObject;
obj.transform.SetParent(content);
obj.transform.localScale = Vector3.one;
child = obj.transform;
}
child.gameObject.name = index.ToString();
items.Add(child);
return child as RectTransform;
}
// Set up resources
public void SetItem(GameObject child)
{
if (child == null) return;
this.item = child;
RectTransform itemTrans = child.transform as RectTransform;
itemTrans.pivot = new Vector2(0, 1);
itemSize = itemTrans.sizeDelta;
//ReBuild();
}
// Update the number of renderings needed
public void SetChildCount(int value, bool forceRender)
{
if (value < 0) childCount = 0;
else childCount = value;
if (totalCount <= 0)// Not initialized yet
return;
if (value > items.Count && items.Count < maxPerLine * totalCount)
{
// The current number of grids is less than the number that should be generated
int count = items.Count;
int max = value < maxPerLine * totalCount ? value : maxPerLine * totalCount;
for (int i = count; i < max; i++)
{
int row = i / maxPerLine;
int col = i % maxPerLine;
RectTransform child = CreateItem(i);
if (arrangement == Arrangement.Vertical)
child.localPosition = startPos +
new Vector2(col * itemSize.x + (col) * columuSpace,
-row * itemSize.y - (row) * rowSpace);
else
child.localPosition = startPos +
new Vector2(row * itemSize.x + (row) * columuSpace,
-col * itemSize.y - (col) * rowSpace);
}
}
if (content == null) return;
int rc = Mathf.CeilToInt((float)childCount / (float)maxPerLine); // Set up content Size
if (arrangement == Arrangement.Horizontal)
{
content.sizeDelta = new Vector2(marginLeft + marginRight + itemSize.x * rc + columuSpace * (rc - 1),
viewPort.y);
if (content.sizeDelta.x > viewPort.x && content.anchoredPosition.x < viewPort.x - content.sizeDelta.x)
content.anchoredPosition = new Vector2(viewPort.x - content.sizeDelta.x, content.anchoredPosition.y);
}
else
{
content.sizeDelta = new Vector2(viewPort.x, marginTop + marginBottom + itemSize.y * rc + rowSpace * (rc - 1));
if (content.sizeDelta.y > viewPort.y && content.anchoredPosition.y > content.sizeDelta.y - viewPort.y)
content.anchoredPosition = new Vector2(content.anchoredPosition.x, content.sizeDelta.y - viewPort.y);
}
UpdateRectItem(GetCurLineIndex(), true);
}
// Add child nodes
public void AddChild(int index)
{
if (index < 0) return;
startIndex = scrollLineIndex * maxPerLine;
endIndex = (scrollLineIndex + totalCount) * maxPerLine;
SetChildCount(childCount + 1, index >= startIndex && index < endIndex);
}
// Delete child nodes
public void RemoveChild(int index)
{
if (index < 0 || index >= childCount) return;
startIndex = scrollLineIndex * maxPerLine;
endIndex = (scrollLineIndex + totalCount) * maxPerLine;
SetChildCount(childCount - 1, index >= startIndex && index < endIndex);
}
// <summary>
// Set the display window size ( It seems that it can be abandoned now )
public void SetViewPort(Vector2 port)
{
if (port == viewPort) return;
viewPort = port;
//ReBuild();
}
// Set the row and column maximum
public void SetMaxPerLine(int max)
{
maxPerLine = max;
//ReBuild();
}
// Return to the top
public void BackTop()
{
content.localPosition = Vector3.zero;
UpdateRectItem(0, true);
}
// Go back to the bottom
public void BackBottom()
{
if (arrangement == Arrangement.Vertical)
{
content.localPosition = new Vector3(0, -viewPort.y + content.sizeDelta.y, 0);
}
else
{
content.localPosition = new Vector3(viewPort.x - content.sizeDelta.x, 0);
}
UpdateRectItem(Mathf.CeilToInt((float)childCount / (float)maxPerLine) - totalCount + 1, true);
}
public void RefreshViewItem()
{
UpdateRectItem(scrollLineIndex, true);
}
public void SetArrangement(int arr)
{
arrangement = (Arrangement)arr;
}
public void SetHorizontal(int h)
{
horizontalAlign = (HorizontalAlign)h;
}
public void SetVerticle(int v)
{
verticalAlign = (VerticalAlign)v;
}
public void AddChangeItemListener(Action<Transform, int> handle)
{
_handle = handle;
}
} Example :
Lua Application example :
local Tool = require("Tool")
local SprogExtendWindow = {}
local mediate = nil
local gridView = nil
local extendItem = nil
local extendItemInfo = nil
local sortList = nil
local extendCfgs = nil
local rewardState =
{
UNFINISH = 0, -- Can claim
UNREACH = 1, -- Not achieved
FINISHED = 2, -- Have received
}
function SprogExtendWindow.Init(data)
mediate = data
-- establish ITEM example
ResMgr.LoadAssets("prefab", { "SprogExtendItem" },function(objs)
extendItem = objs[0]
end)
extendItemInfo = {} -- The server sends data
sortList = {} -- The front end has been sorted , Data for display
SprogExtendWindow.InitGridView()
SprogExtendWindow.RegistEvents()
SprogExtendWindow.UpdateAllExtendInfo()
return SprogExtendWindow
end
function SprogExtendWindow.InitGridView()
gridView = mediate:FindChild("Layer_Sprite/panelGroup/extendPanel/bottom/Scroll View"):GetComponent("UIGridView") -- obtain UIGridView Components
gridView.maxPerLine = 1
gridView.rowSpace = 1
gridView:SetItem(extendItem)
gridView:SetViewPort(Vector2(565,325))
-- stay ScrollView OnSwipe ,UIGridView Will recall the upcoming item, The client only needs to fill in the corresponding UI data .
-- PS: This function will keep calling , We have to consider performance , Avoid dealing with too large data
gridView:AddChangeItemListener(function(transform, index)
local index = index + 1
if sortList and sortList[index] then
local item = sortList[index]
Tool.subGetObject(transform, "time", "Text").text = item.config.time .. " " .. item.config.id
Tool.subGetObject(transform, "content", "Text").text = item.config.name
Tool.subGetObject(transform, "image", "Image").sprite = Tool.LoadImgSpriteFromAb("image", item.config.img)
SprogExtendWindow.SetStateInfo(item.state, transform)
transform:FindChild("Button").onClick = function(obj, eventData)
SprogExtendWindow.CheckExtendItemInfo(item.config.id, transform)
end
end
end)
end
function SprogExtendWindow.RegistEvents()
mediate:AddClick("Layer_Sprite/panelGroup/extendPanel/top/btn_num", function ()
log(" Button 1")
end)
mediate:AddClick("Layer_Sprite/panelGroup/extendPanel/top/btn_link", function ()
log(" Button 2")
end)
mediate:AddClick("Layer_Sprite/panelGroup/extendPanel/top/btn_share", function ()
log(" Button 3")
end)
end
function SprogExtendWindow.InitScrollView()
end
function SprogExtendWindow.UpdateAllExtendInfo()
-- TEST, Select temporary data
local data =
{
[1] = {id = 1, type = 1, time = "2020.01.01", name = " The bed ", img = "yxdt_tx1.png", vip = 1, liquanNum = 99999},
[2] = {id = 2, type = 1, time = "2020.01.02", name = " front ", img = "yxdt_tx1.png", vip = 2, liquanNum = 99999},
[3] = {id = 3, type = 1, time = "2020.01.03", name = " bright ", img = "yxdt_tx1.png", vip = 3, liquanNum = 99999},
[4] = {id = 4, type = 1, time = "2020.01.04", name = " month ", img = "yxdt_tx1.png", vip = 4, liquanNum = 99999},
[5] = {id = 5, type = 1, time = "2020.01.05", name = " light ", img = "yxdt_tx1.png", vip = 5, liquanNum = 99999},
[6] = {id = 6, type = 1, time = "2020.01.06", name = " The bed ", img = "yxdt_tx1.png", vip = 6, liquanNum = 99999},
[7] = {id = 7, type = 1, time = "2020.01.07", name = " front ", img = "yxdt_tx1.png", vip = 7, liquanNum = 99999},
[8] = {id = 8, type = 1, time = "2020.01.08", name = " bright ", img = "yxdt_tx1.png", vip = 8, liquanNum = 99999},
[9] = {id = 9, type = 1, time = "2020.01.09", name = " month ", img = "yxdt_tx1.png", vip = 9, liquanNum = 99999},
[10] = {id = 10, type = 1, time = "2020.01.10", name = " light ", img = "yxdt_tx1.png", vip = 10, liquanNum = 99999},
[11] = {id = 11, type = 1, time = "2020.01.01", name = " The bed ", img = "yxdt_tx1.png", vip = 1, liquanNum = 99999},
[12] = {id = 12, type = 1, time = "2020.01.02", name = " front ", img = "yxdt_tx1.png", vip = 2, liquanNum = 99999},
[13] = {id = 13, type = 1, time = "2020.01.03", name = " bright ", img = "yxdt_tx1.png", vip = 3, liquanNum = 99999},
[14] = {id = 14, type = 1, time = "2020.01.04", name = " month ", img = "yxdt_tx1.png", vip = 4, liquanNum = 99999},
[15] = {id = 15, type = 1, time = "2020.01.05", name = " light ", img = "yxdt_tx1.png", vip = 5, liquanNum = 99999},
[16] = {id = 16, type = 1, time = "2020.01.06", name = " The bed ", img = "yxdt_tx1.png", vip = 6, liquanNum = 99999},
[17] = {id = 17, type = 1, time = "2020.01.07", name = " front ", img = "yxdt_tx1.png", vip = 7, liquanNum = 99999},
[18] = {id = 18, type = 1, time = "2020.01.08", name = " bright ", img = "yxdt_tx1.png", vip = 8, liquanNum = 99999},
[19] = {id = 19, type = 1, time = "2020.01.09", name = " month ", img = "yxdt_tx1.png", vip = 9, liquanNum = 99999},
[20] = {id = 20, type = 1, time = "2020.01.10", name = " light ", img = "yxdt_tx1.png", vip = 10, liquanNum = 99999},
[21] = {id = 21, type = 1, time = "2020.01.01", name = " The bed ", img = "yxdt_tx1.png", vip = 1, liquanNum = 99999},
[22] = {id = 22, type = 1, time = "2020.01.02", name = " front ", img = "yxdt_tx1.png", vip = 2, liquanNum = 99999},
[23] = {id = 23, type = 1, time = "2020.01.03", name = " bright ", img = "yxdt_tx1.png", vip = 3, liquanNum = 99999},
[24] = {id = 24, type = 1, time = "2020.01.04", name = " month ", img = "yxdt_tx1.png", vip = 4, liquanNum = 99999},
[25] = {id = 25, type = 1, time = "2020.01.05", name = " light ", img = "yxdt_tx1.png", vip = 5, liquanNum = 99999}
}
extendItemInfo = {}
for k, v in ipairs(data) do
extendItemInfo[v.id] =
{
config = v, -- Local configuration
state = math.random(0, 2) -- A random state
}
end
SprogExtendWindow.OnSortAllExtendItem()
gridView.ChildCount = #sortList -- Set up current item total
gridView:ReBuild() -- start-up UIGridView
end
-- Sort the data and sort
function SprogExtendWindow.OnSortAllExtendItem()
-- Press rewardState grouping , Can claim > Not achieved > Have received
local templist = {}
for index = 1, 3 do
for _,v in ipairs(extendItemInfo) do
if index == v.state + 1 then
if templist[index] == nil then
templist[index] = {}
end
table.insert(templist[index], v)
end
end
end
-- Each group by VIP Rank order
for _,v in ipairs(templist) do
table.sort(v, function (a, b)
return a.config.vip > b.config.vip
end)
end
sortList = {}
for _,v in ipairs(templist) do
for _,m in ipairs(v) do
table.insert(sortList, m)
end
end
-- log(" List after sorting " .. tostring(sortList))
end
function SprogExtendWindow.SetStateInfo(state, obj)
local text = nil
local isInteract = nil
if state == rewardState.UNREACH then
text = " Not achieved "
isInteract = false
elseif state == rewardState.UNFINISH then
text = " Can claim "
isInteract = true
elseif state == rewardState.FINISHED then
text = " Have received "
isInteract = false
end
obj.transform:FindChild("Button").interactable = isInteract
Tool.subGetObject(obj, "Button/Text", "Text").text = text
end
function SprogExtendWindow.CheckExtendItemInfo(id, obj)
if extendItemInfo ~= nil and extendItemInfo[id] ~= nil then
local item = extendItemInfo[id]
local reqSuccess = function(www)
--local data = Json.decode(www.text).data
log(" Claim success ,data: " .. CC.uu.Dump(data))
item.state = 2
SprogExtendWindow.SetStateInfo(item.state, obj)
end
local reqFailed = function(err)
log(" Failed to collect :" .. tostring(err))
end
-- Send a request
local Url = Tool.UrlMgr.UrlMapping("http://172.0.0.1:8000/GetTestData", {id = id, channelId = id})
Tool.HttpPost(Url, nil, reqSuccess, reqSuccess)
end
end
function SprogExtendWindow.Destroy()
end
return SprogExtendWindow
Unity Component mount :




边栏推荐
- Three. Introduction to JS learning notes 17: mouse control of 3D model rotation of JSON file
- 【数字IC验证快速入门】20、SystemVerilog学习之基本语法7(覆盖率驱动...内含实践练习)
- It's different for rich people to buy a house
- A link opens the applet code. After compilation, it is easy to understand
- The "go to definition" in VS2010 does not respond or prompts the solution of "symbol not found"
- webgl_ Enter the three-dimensional world (1)
- Getting started with webgl (4)
- numpy--数据清洗
- Learn good-looking custom scroll bars in 1 minute
- Vertex shader to slice shader procedure, varying variable
猜你喜欢
![Super signature principle (fully automated super signature) [Yun Xiaoduo]](/img/b8/5bafbada054b335568e64c7e1ac6bb.jpg)
Super signature principle (fully automated super signature) [Yun Xiaoduo]

Spin animation of Cocos performance optimization

Numpy -- data cleaning

LeetCode2_ Add two numbers

Asynchronous application of generator function

C4D learning notes 2- animation - timeline and time function

Three. JS introductory learning notes 04: external model import - no material obj model

航運船公司人工智能AI產品成熟化標准化規模應用,全球港航人工智能/集裝箱人工智能領軍者CIMC中集飛瞳,打造國際航運智能化標杆

LeetCode1_ Sum of two numbers

【数字IC验证快速入门】18、SystemVerilog学习之基本语法5(并发线程...内含实践练习)
随机推荐
Cocos uses custom material to display problems
深度之眼(六)——矩阵的逆(附:logistic模型一些想法)
[quick start of Digital IC Verification] 25. AHB sramc of SystemVerilog project practice (5) (AHB key review, key points refining)
[quick start of Digital IC Verification] 19. Basic grammar of SystemVerilog learning 6 (thread internal communication... Including practical exercises)
15. Using the text editing tool VIM
Tkinter after how to refresh data and cancel refreshing
Cocos makes Scrollview to realize the effect of zooming in the middle and zooming out on both sides
Do not use memset to clear floating-point numbers
Numpy -- epidemic data analysis case
Three. JS introductory learning notes 10:three JS grid
如何在shell中实现 backspace
[quick start of Digital IC Verification] 20. Basic grammar of SystemVerilog learning 7 (coverage driven... Including practical exercises)
喜讯!科蓝SUNDB数据库与鸿数科技隐私数据保护管理软件完成兼容性适配
过度依赖补助,大客户收款难,冲刺“国产数据库第一股”的达梦后劲有多足?
Streaming end, server end, player end
神经网络c语言中的指针是怎么回事
招标公告:福建省农村信用社联合社数据库审计系统采购项目(重新招标)
Cocos creator collision and collision callback do not take effect
webgl_ Enter the three-dimensional world (1)
Please supervise the 2022 plan