364 lines
13 KiB
C#
364 lines
13 KiB
C#
|
//**********************************************//
|
|||
|
//作者:#何健#
|
|||
|
//日期:#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;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|