当前位置:网站首页>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 :
边栏推荐
- AE learning 02: timeline
- Iterator and for of.. loop
- Syntaxhighlight highlights the right scroll bar
- How to understand that binary complement represents negative numbers
- Starting from 1.5, build a microservice framework link tracking traceid
- Limit of total fields [1000] in index has been exceeded
- Cut ffmpeg as needed, and use emscripten to compile and run
- Three. JS introductory learning notes 15: threejs frame animation module
- Three. JS introductory learning notes 0: illustration of how webgl and threejs work
- 招标公告:福建省农村信用社联合社数据库审计系统采购项目(重新招标)
猜你喜欢
Getting started with webgl (1)
航运船公司人工智能AI产品成熟化标准化规模应用,全球港航人工智能/集装箱人工智能领军者CIMC中集飞瞳,打造国际航运智能化标杆
The rebound problem of using Scrollview in cocos Creator
numpy--疫情数据分析案例
How does geojson data merge the boundaries of regions?
Vertex shader to slice shader procedure, varying variable
2022 all open source enterprise card issuing network repair short website and other bugs_ 2022 enterprise level multi merchant card issuing platform source code
Mesh merging under ue4/ue5 runtime
HW primary flow monitoring, what should we do
Three. JS introductory learning notes 19: how to import FBX static model
随机推荐
Three. Introduction to JS learning notes 17: mouse control of 3D model rotation of JSON file
Actually changed from 408 to self proposition! 211 North China Electric Power University (Beijing)
Syntax of generator function (state machine)
Getting started with webgl (3)
Three. JS introductory learning notes 07: external model import -c4d to JSON file for web pages -fbx import
[markdown grammar advanced] make your blog more exciting (IV: set font style and color comparison table)
Syntaxhighlight highlights the right scroll bar
What is Base64?
保证接口数据安全的10种方案
15. Using the text editing tool VIM
numpy--数据清洗
Ida Pro reverse tool finds the IP and port of the socket server
./ Functions of configure, make and make install
Super signature principle (fully automated super signature) [Yun Xiaoduo]
AE learning 01: AE complete project summary
C Alibaba cloud OSS file upload, download and other operations (unity is available)
LeetCode1_ Sum of two numbers
Webcodecs parameter settings -avc1.42e01e meaning
Please supervise the 2022 plan
Virtual memory, physical memory /ram what