Files
Main/Assets/GameAssets/Resources/GameUI/Common/UILoopScrollView/UILoopScrollViewBase.cs

364 lines
13 KiB
C#
Raw Normal View History

2025-01-25 04:38:09 +08:00
//**********************************************//
//作者:#何健#
//日期:#2016.10.09#
//简述:#ScrollView优化使用一定数量子项实现大量数据循环加载#
//*********************************************//
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Thousandto.Plugins.Common
{
/// <summary>
/// 类BackPackItem说明
/// </summary>
[RequireComponent(typeof(UIGrid))]
public class UILoopScrollViewBase : MonoCacheBase
{
#region Members
/// <summary>
/// 存储物件列表
/// </summary>
private List<GameObject> m_itemList = new List<GameObject>();
/// <summary>
/// 起始下标
/// </summary>
private int _startIndex = 1;
/// <summary>
/// 最大长度
/// </summary>
private int _maxCount;
/// <summary>
/// 父ScrollView
/// </summary>
public UIScrollView _scrollView;
/// <summary>
/// grid
/// </summary>
public UIGrid _grid;
/// <summary>
/// templateItem
/// </summary>
public GameObject _templateItem;
/// <summary>
/// 物件刷新代理事件
/// </summary>
/// <param name="go"></param>
public delegate void OnItemChange(Transform obj, string name, bool isClear);
private OnItemChange m_pItemChangeCallBack;
private Vector2 _scrollViewPos = new Vector2(0, 0);
private Vector3 lastPos;
private bool _isRecodePos = false;
#endregion
#region
/// <summary>
/// 设置代理
/// </summary>
/// <param name="_onItemChange"></param>
public void SetDelegate(OnItemChange _onItemChange)
{
m_pItemChangeCallBack = _onItemChange;
}
/// <summary>
/// 物件刷新代理事件
/// </summary>
/// <param name="go"></param>
private void OnItemChangeMsg(Transform obj,string name, bool isClear)
{
if (m_pItemChangeCallBack != null)
{
m_pItemChangeCallBack(obj, name, isClear);
}
}
#endregion
/// <summary>
/// 初始化表
/// </summary>
public void Init(int maxCount, GameObject templateItem = null, int waitCount = 1, bool isResetScrool = true)
{
_isRecodePos = false;
_maxCount = maxCount;
if (isResetScrool)
{
// 如果传入有控件则以传入的为模板如果没有则查找grid下面第一个子控件
_grid = transform.GetComponent<UIGrid>();
_scrollView = transform.parent.GetComponent<UIScrollView>();
_grid.gameObject.SetActive(true);
var _num = _maxCount % _grid.maxPerLine;
if (_num != 0)
{
_maxCount = _maxCount + _grid.maxPerLine - _num;
}
if (templateItem)
{
_templateItem = templateItem;
}
else
{
_templateItem = _grid.transform.GetChild(0).gameObject;
}
try
{
StartCoroutine(Respositon(waitCount));
}
finally
{
}
}
else
{
//当前显示出来的第一个格子在grid数据中的index
var childCount = _grid.transform.childCount;
int index = Mathf.FloorToInt((_maxCount - childCount) / _grid.maxPerLine);
for (int i = index * _grid.maxPerLine; i < childCount + index * _grid.maxPerLine; i++)
{
if (i >= _maxCount)
return;
FillItem(i - index * _grid.maxPerLine + _startIndex, i + _startIndex, i == childCount + index * _grid.maxPerLine - 1);
}
}
}
private IEnumerator Respositon(int waitCount = 0)
{
InitGird();
_grid.Reposition();
yield return waitCount;
_scrollView.ResetPosition();
_isRecodePos = true;
}
private void InitGird()
{
m_itemList.Clear();
// 将现有的子项添加到容器
for (int i = 0; i < _grid.transform.childCount; i++)
{
GameObject go = _grid.transform.GetChild(i).gameObject;
//go.SetActive(false);
m_itemList.Add(go);
}
int fillCount = 0; //当前scrollView被填满的格子数
int lastIndex = 0; //上次显示出来的第一个格子在grid数据中的index
var _indexDis = 0f;
UIPanel panel = _scrollView.GetComponent<UIPanel>();
if (_scrollView.movement == UIScrollView.Movement.Vertical)
{
fillCount = Mathf.CeilToInt(panel.height / _grid.cellHeight);
fillCount = fillCount * _grid.maxPerLine;
_indexDis = _grid.cellHeight;
}
else if (_scrollView.movement == UIScrollView.Movement.Horizontal)
{
fillCount = Mathf.CeilToInt(panel.width / _grid.cellWidth);
_indexDis = _grid.cellWidth;
}
//if (_maxCount < fillCount + _grid.maxPerLine)
// _maxCount = fillCount + _grid.maxPerLine;
int childCount = _maxCount;
// 如果item数量大于填满显示面板的数量做优化
if (childCount > fillCount + _grid.maxPerLine)
{
childCount = fillCount + _grid.maxPerLine;
// 拖拽刷新面板
panel.onClipMove = (uiPanel) => {
Vector3 delata = lastPos - panel.transform.localPosition;
float distance = System.Math.Abs(delata.y) > 0.5 ? delata.y : delata.x;
// 满的时候向上滑不管它
if ((distance > 0 && _scrollView.movement == UIScrollView.Movement.Vertical) || (distance < 0 && _scrollView.movement == UIScrollView.Movement.Horizontal))
return;
if (distance < 0)
distance = -distance;
//当前显示出来的第一个格子在grid数据中的index
int index = Mathf.FloorToInt(distance / _indexDis);
// 拖拽不满一个单元格
if (index == lastIndex) return;
// 拉到底了
if (index + childCount > _maxCount) {
for (int i = 1; i <= _grid.transform.childCount; i++)
{
if (i >= _maxCount)
return;
var _newKey = _maxCount >= _grid.transform.childCount ? _maxCount - _grid.transform.childCount + i : i;
FillItem(i, _newKey, i == _grid.transform.childCount);
}
return;
}
lastIndex = index;
// 重刷
if ((index - 1) * _grid.maxPerLine + childCount < _maxCount)
{
for (int i = index * _grid.maxPerLine; i < childCount + index * _grid.maxPerLine; i++)
{
if (i >= _maxCount)
return;
FillItem(i - index * _grid.maxPerLine + _startIndex, i + _startIndex, i == childCount + index * _grid.maxPerLine - 1);
}
}
};
}
_scrollView.onStoppedMoving = OnDragFinished;
// 添加能填满UI数量的子项
var allCount = fillCount + _grid.maxPerLine;
for (int i = 0; i < allCount; i++)
{
bool isClear = false;
if (i == 0)
{
isClear = true;
}
if (i >= _maxCount)
{
break;
}
GameObject go = null;
if (i < m_itemList.Count)
{
go = m_itemList[i];
}
else
{
go = NGUITools.AddChild(_grid.gameObject, _templateItem);
m_itemList.Add(go);
}
go.SetActive(true);
FillItem(i + _startIndex, i + _startIndex, isClear);
//if (m_itemList.Count > i)
//{
// FillItem(i + _startIndex, i + _startIndex, isClear);
// continue;
//}
//GameObject go = NGUITools.AddChild(_grid.gameObject, _templateItem);
//go.SetActive(true);
//m_itemList.Add(go);
//FillItem(i + _startIndex, i + _startIndex, isClear);
}
for (int i = allCount; i < m_itemList.Count; i++)
{
m_itemList[i].SetActive(false);
}
lastPos = panel.transform.localPosition;
}
public void OnDragFinished()
{
if (_scrollView.movement == UIScrollView.Movement.Vertical)
{
int indexY = (int)_scrollViewPos.y;
if (indexY + 10 > (int)_scrollView.transform.localPosition.y && indexY - 10 < (int)_scrollView.transform.localPosition.y)
{
for (int i = 0; i < _grid.transform.childCount; i++)
{
if (i >= _maxCount)
return;
FillItem(i + _startIndex, i + _startIndex, i == _grid.transform.childCount - 1);
}
}
}
else if(_scrollView.movement == UIScrollView.Movement.Horizontal)
{
int indexY = (int)_scrollViewPos.x;
if (indexY + 10 > (int)_scrollView.transform.localPosition.x && indexY - 10 < (int)_scrollView.transform.localPosition.x)
{
for (int i = 0; i < _grid.transform.childCount; i++)
{
if (i >= _maxCount)
return;
FillItem(i + _startIndex, i + _startIndex, i == _grid.transform.childCount - 1);
}
}
}
}
// 修改子项位置
public void FillItem(int oldIndex, int index, bool isClear)
{
//Debug.Log("-----oldIndex=" + oldIndex + ",index = " + index + ", itemListCount=" + m_itemList.Count);
int iListIndex = oldIndex - _startIndex;
if (m_itemList.Count <= iListIndex)
return;
string oldKey = m_itemList[iListIndex].name;
string newKey = index.ToString();
m_itemList[iListIndex].name = newKey;
if (_scrollView.movement == UIScrollView.Movement.Horizontal)// 如果是水平滑动,则只有一排
{
m_itemList[iListIndex].transform.localPosition = new Vector3(_grid.cellWidth * (index - 1), 0, 0);
}
else if (_scrollView.movement == UIScrollView.Movement.Vertical) // 纵向滑动时有可能有多列
{
int count = index / _grid.maxPerLine;
int countLess = index % _grid.maxPerLine;
if(countLess == 0)
{
countLess = _grid.maxPerLine - _startIndex;
if(_startIndex != 0)
{
count -= 1;
}
}
else
{
countLess -= _startIndex;
}
m_itemList[iListIndex].transform.localPosition = new Vector3(countLess * _grid.cellWidth, -_grid.cellHeight * count, 0);
m_itemList[iListIndex].gameObject.SetActive(true);
}
OnItemChangeMsg(m_itemList[iListIndex].transform, newKey, isClear);
}
// 修改最大格子数
public void OnSetMaxIndex(int max)
{
_maxCount = max;
if(_grid != null)
{
var _num = _maxCount % _grid.maxPerLine;
if (_num != 0)
{
_maxCount = _maxCount - _grid.maxPerLine + _num;
}
}
}
// 修改最大格子数
public int OnGetMaxIndex()
{
return _maxCount;
}
//重置lastpos
public void ResetPos()
{
lastPos = _scrollView.GetComponent<UIPanel>().transform.localPosition;
}
private void Update()
{
if (_isRecodePos)
{
_scrollViewPos = _scrollView.transform.localPosition;
ResetPos();
_isRecodePos = false;
}
}
}
}