当前位置:网站首页>Scrollrect for tableview
Scrollrect for tableview
2022-06-22 07:36:00 【Liam666】
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.EventSystems;
class TableViewGroup
{
public Dictionary<int, RectTransform> visibilityCellQueue = new Dictionary<int, RectTransform>();
public List<RectTransform> invisibilityCellQueue = new List<RectTransform>();
~TableViewGroup()
{
visibilityCellQueue.Clear();
visibilityCellQueue = null;
invisibilityCellQueue.Clear();
invisibilityCellQueue = null;
}
public void QueueInvisible()
{
foreach(int i in visibilityCellQueue.Keys) {
RectTransform trans = visibilityCellQueue[i];
invisibilityCellQueue.Add(trans);
trans.gameObject.SetActive(false);
}
visibilityCellQueue.Clear();
}
}
public class TableView : ScrollRect
{
public const string DEFAULT_IDENTIFIER = "default.identifier";
public delegate int NumberOfCells(TableView tbView);
public delegate float SizeOfIndex(TableView tbView, int index);
public delegate RectTransform TransformOfIndex(TableView tbView, int index);
public delegate string IdentifierOfIndex(TableView tbView, int index);
/// <summary>
/// Returns the number of rows
/// </summary>
public NumberOfCells delegateNumberOfCells = null;
/// <summary>
/// explain : Back to page i That's ok cell Height ( vertical ), Or width ( level )
/// Parameters
/// t: TableView
/// i: int What line is it
/// </summary>
public SizeOfIndex delegateSizeOfIndex = null;
/// <summary>
/// explain : Back to page i That's ok cell Of RectTransform
/// Parameters
/// t: TableView
/// i: int What line is it
/// </summary>
public TransformOfIndex delegateTransformOfIndex = null;
/// <summary>
/// explain : Back to page i That's ok cell Identifier
/// Parameters
/// t: TableView
/// i: int What line is it
/// </summary>
public IdentifierOfIndex delegateIdentifierOfIndex = null;
int extraBuffer = 2;
private Rect[] rects;
private Dictionary<string, TableViewGroup> groupDict = new Dictionary<string, TableViewGroup>();
private int numberOfCells = 0;
private int minVisibleIndex = 0;
private int maxVisibleIndex = 0;
protected override void OnDestroy()
{
delegateNumberOfCells = null;
delegateSizeOfIndex = null;
delegateTransformOfIndex = null;
delegateIdentifierOfIndex = null;
base.OnDestroy();
}
protected override void Start()
{
base.Start();
onValueChanged.AddListener(OnMove);
}
bool IsIdentifierExist(string identifier)
{
return groupDict.ContainsKey(identifier + "_v");
}
void OnMove(Vector2 value)
{
if (numberOfCells == 0) return;
UpdateMinMaxVisibleIndex();
}
/// <summary>
/// Sliding cycle ITEM
/// </summary>
private void UpdateMinMaxVisibleIndex()
{
Vector2 minMaxIndexes = GetMinMaxVisibleIndex();
int minIndex = (int)minMaxIndexes.x;
int maxIndex = (int)minMaxIndexes.y;
if(minVisibleIndex == minIndex || maxVisibleIndex == maxIndex) return;
if (minVisibleIndex - minIndex < 0)
{
for (int i = minVisibleIndex; i < minIndex; i++)
{
RemoveCellAtIndex(i);
}
for (int i = maxVisibleIndex; i <= maxIndex; i++)
{
AddCellAtIndex(i);
}
}
else
{
for (int i = minVisibleIndex; i >= minIndex; i--)
{
AddCellAtIndex(i);
}
for (int i = maxVisibleIndex; i > maxIndex; i--)
{
RemoveCellAtIndex(i);
}
}
minVisibleIndex = minIndex;
maxVisibleIndex = maxIndex;
}
private void AddCellAtIndex(int index)
{
if (index >= numberOfCells || index < 0) return;
string identifier = GetIdentifierForIndex(index);
if (groupDict[identifier].visibilityCellQueue.ContainsKey(index) == false)
{
Rect rect = rects[index];
RectTransform trans = delegateTransformOfIndex(this, index);
//trans.anchorMin = new Vector2(0.5f, 0.5f);
//trans.anchorMax = new Vector2(0.5f, 0.5f);
trans.SetParent(content);
//trans.anchoredPosition = new Vector2(rect.x, rect.y);
trans.localRotation = new Quaternion(0, 0, 0, 0);
trans.localScale = Vector3.one;
if (vertical)
{
trans.anchoredPosition = new Vector2(rect.x, rect.y - rect.height / 2f);
trans.anchorMin = new Vector2(0f, 1f);
trans.anchorMax = new Vector2(1f, 1f);
trans.pivot = new Vector2(0.5f, 0.5f);
Vector2 v = trans.offsetMin;
v.x = 0;
trans.offsetMin = v;
v = trans.offsetMax;
v.x = 0;
trans.offsetMax = v;
}
else
{
trans.anchoredPosition = new Vector2(rect.x + rect.width / 2f, rect.y);
trans.anchorMin = new Vector2(0f, 0.5f);
trans.anchorMax = new Vector2(0f, 0.5f);
trans.pivot = new Vector2(0.5f, 0.5f);
}
groupDict[identifier].visibilityCellQueue.Add(index, trans);
}
}
private void RemoveCellAtIndex(int index)
{
string identifier = GetIdentifierForIndex(index);
if (groupDict[identifier].visibilityCellQueue.ContainsKey(index) == true)
{
RectTransform trans = groupDict[identifier].visibilityCellQueue[index];
groupDict[identifier].invisibilityCellQueue.Add(trans);
groupDict[identifier].visibilityCellQueue.Remove(index);
trans.gameObject.SetActive(false);
}
}
private int IndexAtOffset(float offset)
{
int minIndex = 0;
int maxIndex = numberOfCells - 1;
maxIndex = maxIndex < 0 ? 0 : maxIndex;
int index = (maxIndex + minIndex) / 2;
if (vertical)
{
while (minIndex < maxIndex)
{
float indexY = rects[index].y;
float nextY = rects[index + 1].y;
if (indexY >= offset && nextY < offset) break;
else if (nextY >= offset) minIndex = index + 1;
else maxIndex = index;
index = (maxIndex + minIndex) / 2;
}
}
else
{
while (minIndex < maxIndex)
{
float indexX = -rects[index].x;
float nextX = -rects[index + 1].x;
if (indexX >= offset && nextX < offset) break;
else if (nextX >= offset) minIndex = index + 1;
else maxIndex = index;
index = (maxIndex + minIndex) / 2;
}
}
return index;
}
private Vector2 GetMinMaxVisibleIndex()
{
RectTransform trans = transform as RectTransform;
Vector2 offset = content.anchoredPosition;
float viewWidth = trans.rect.width;
float viewHeight = trans.rect.height;
int minIndex = vertical ? IndexAtOffset(-offset.y) : IndexAtOffset(offset.x);
int maxIndex = vertical ? IndexAtOffset(-offset.y - viewHeight) : IndexAtOffset(offset.x - viewWidth);
int boundMinIndex = 0;
int boundMaxIndex = numberOfCells - 1;// Mathf.Max(0, numberOfCells - 1);
minIndex = minIndex - extraBuffer / 2;
minIndex = minIndex < boundMinIndex ? boundMinIndex : minIndex;
maxIndex = maxIndex + extraBuffer / 2;
maxIndex = maxIndex > boundMaxIndex ? boundMaxIndex : maxIndex;
return new Vector2(minIndex, maxIndex);
}
/// <summary>
/// Reload data +
/// </summary>
/// <param name="startIndex"> After reloading, jump to startIndex That's ok , Such as :10, Jump to the first place 10 That's ok . another :-1, Jump to the first place 0 That's ok , And execute the bounce animation ;-2, Refresh on the current line </param>
public void ReloadData(int startIndex = 0, bool isLerp = false, bool cleanCell = false)
{
RectTransform trans = transform as RectTransform;
float viewWidth = trans.rect.width;
float viewHeight = trans.rect.height;
if (cleanCell)
{
groupDict.Clear();
while (content.childCount > 0)
{
//PoolManager.instance.recycle(content.GetChild(0).gameObject);
}
}
else
{
foreach(string identifier in groupDict.Keys)
{
groupDict[identifier].QueueInvisible();
}
}
numberOfCells = delegateNumberOfCells(this);
rects = new Rect[numberOfCells];
float offsetX = 0f;
float offsetY = 0f;
float width = 0;
float x = 0;
float height = 0;
float y = 0;
Vector2 contentPos = content.anchoredPosition;
Vector2 contentSize = content.sizeDelta;
System.Action<int> createIdentifierGroup = null;
if (delegateIdentifierOfIndex == null)
{
if(groupDict.ContainsKey(DEFAULT_IDENTIFIER) == false) groupDict[DEFAULT_IDENTIFIER] = new TableViewGroup();
}
else
{
createIdentifierGroup = (i) =>
{
string identifier = delegateIdentifierOfIndex(this, i);
if (groupDict.ContainsKey(identifier) == false) groupDict[identifier] = new TableViewGroup();
};
}
if (vertical)
{
for (int i = 0; i < numberOfCells; i++)
{
height = delegateSizeOfIndex(this, i);
rects[i] = new Rect(0, -y, viewWidth, height);
y += height;
if (i < startIndex) offsetY += height;
if (createIdentifierGroup != null) createIdentifierGroup(i);
}
contentSize.y = y;
}
else
{
for (int i = 0; i < numberOfCells; i++)
{
width = delegateSizeOfIndex(this, i);
rects[i] = new Rect(x, 0, width, viewHeight);
x += width;
if (i < startIndex) offsetX += width;
if (createIdentifierGroup != null) createIdentifierGroup(i);
}
contentSize.x = x;
}
content.sizeDelta = contentSize;
if (startIndex >= 0)
{
if (vertical) contentPos.y = offsetY;
else contentPos.x = -offsetX;
if (isLerp)
{
ExecuteContentLerp(contentPos);
}
else
{
content.anchoredPosition = contentPos;
}
}
else if (startIndex == -1)
{
normalizedPosition = Vector2.zero;
}
Vector2 indexes = GetMinMaxVisibleIndex();
minVisibleIndex = (int)indexes.x;
maxVisibleIndex = (int)indexes.y;
if (numberOfCells > 0)
{
for (int i = minVisibleIndex; i <= maxVisibleIndex; i++)
{
AddCellAtIndex(i);
}
}
}
public void ToBottom()
{
RectTransform trans = transform as RectTransform;
ReloadData(-2);
if (this.content.sizeDelta.y > trans.rect.height)
{
content.anchoredPosition = new Vector2(content.anchoredPosition.x, this.content.sizeDelta.y + trans.rect.height);
}
}
string GetIdentifierForIndex(int index)
{
return delegateIdentifierOfIndex == null ? DEFAULT_IDENTIFIER : delegateIdentifierOfIndex(this, index);
}
public RectTransform DequeueReusabelCell(int index)
{
string identifier = GetIdentifierForIndex(index);
List<RectTransform> invisibilityCellQueue = groupDict[identifier].invisibilityCellQueue;
int count = invisibilityCellQueue.Count;
if (count > 0)
{
RectTransform trans = invisibilityCellQueue[count - 1];
invisibilityCellQueue.RemoveAt(count - 1);
trans.gameObject.SetActive(true);
return trans;
}
return null;
}
public bool enableDragControl = false;
public override void OnDrag(PointerEventData eventData)
{
if (!enableDragControl || (eventData.pointerCurrentRaycast.gameObject != null && isChild(eventData.pointerCurrentRaycast.gameObject.transform)))
base.OnDrag(eventData);
}
bool isChild(Transform t)
{
Transform[] children = this.transform.GetComponentsInChildren<Transform>();
for (int i = 0; i < children.Length; i++)
{
if (t.gameObject == children[i].gameObject)
return true;
}
return false;
}
private IEnumerator ContentLerpIEnum;
/// <summary>
/// Sliding effect
/// </summary>
/// <param name="pos"></param>
private void ExecuteContentLerp(Vector2 pos)
{
if (gameObject.activeInHierarchy)
{
if (ContentLerpIEnum != null) StopCoroutine(ContentLerpIEnum);
ContentLerpIEnum = ContentLerp(pos);
StartCoroutine(ContentLerpIEnum);
}
}
private IEnumerator ContentLerp(Vector2 pos)
{
while (Vector2.Distance(content.anchoredPosition,pos) > 5)
{
content.anchoredPosition = Vector2.Lerp(content.anchoredPosition, pos, 0.7f);
yield return 1f;
}
content.anchoredPosition = pos;
}
}边栏推荐
- Open version - order delivery
- antd——a-upload-dragger拖拽上传组件——基础积累
- Summary of methods for calculating the number of solutions of indefinite equations
- JS 数组扁平化 (递归写法)
- Flutter gets the context, and flutter gets the DOM element location
- Kuangshi brain++ Tianyuan platform megstudio
- [usecols parameter of pd.read\u excel ((), list error reason]
- Wechat applet service provider sub merchant payment order interface
- True MySQL interview question (19) -- Tiktok -- select the list of users who have logged in for two consecutive days every month
- antd 框架:点击链接重开浏览器页面——基础积累
猜你喜欢

RFID仓储管理系统解决方案实施可视化流程

The pit on the school recruitment Road

How to backup the treasures in the store and upload them to multiple stores

Canoe learning notes (9) sending module can Ig diagram

Canoe learning notes (1) illustration of new project and channel configuration steps

A simple examination system based on C language

How to import and upload a CSV generated by a third-party platform to a Taobao store

Detr3d model source code Guide & mmdetection3d construction process

Open version - inventory description

2 lines of text on the right of the left Avatar
随机推荐
Remote Desktop Manager
Authority management of okcc call center
Backup the method of uploading babies in Taobao stores to multiple stores
JS implementation of random generation of 16 bit key -- Basic accumulation
Coursera self driving car Part4 motion planning finalproject principle and key code analysis
Open version - inventory description
Does it matter if you delete the pictures in the picture space after uploading to the store
[common template problems in graph theory] four shortest path solutions and two minimum spanning tree solutions
Crmeb open version 4.3
JS array flattening (recursive writing)
Tikz learning notes (III) marking and intersection of graphics
Open version - write off
Open source get through version - integral function
Idea cannot connect to sqlsms
Taobao assistant can not be used. How to export the baby in the warehouse to backup the data package
各大企业连连出现亏损,环保行业何去何从?
Phpcms mobile portal configuration
White paper on Web page quality of Baidu search engine guides website construction and optimization
简单是最好的网络推广的方法
Summary of methods for calculating the number of solutions of indefinite equations