using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using DG.Tweening;
///
/// 滑动列表的优化,用少量元素显示很多物体. 修改自UIWarpConten 和gLoop --ljp20170328
///
public class ViewList : MonoBehaviour
{
///
/// 元素初始化
///
/// 游戏对象
/// 对象在prefab中的序号
/// 对象在数组中的序号
public delegate void OnInitializeItem(GameObject item, int wrapIndex, int realIndex);
///
/// 元素初始化
///
public OnInitializeItem onInitializeItem;
///
/// 排列
///
public enum Arrangement
{
///
/// 横
///
Horizontal,
///
/// 竖
///
Vertical,
}
///
/// 排列方式
///
public Arrangement arrangeType = Arrangement.Horizontal;
///
/// The width of each of the cells.
///
public float cellWidth = 200f;
///
/// The height of each of the cells.
///
public float cellHeight = 200f;
///
/// 窗口能容纳的 行数 或 列数
///
public int viewCount = 5;
///
/// 对象最小序号
///
public int minIndex = 0;
///
/// 对象最大序号
///
public int maxIndex = 0;
///
///当前对象
///
Transform mTrans;
///
/// 当前RectTransform对象
///
RectTransform mRTrans;
///
/// ScrollRect
///
ScrollRect mScroll;
///
/// 元素预制物体的容器对象
///
public Transform content = null;
///
/// 元素预制物体
///
public GameObject goItemPrefab = null;
///
/// 最少需要多少预制物体
///
public int mMinNum = 0;
///
/// 滚动方向
///
bool mHorizontal;
///
/// 元素链表
///
List mChild = new List();
///
/// 显示区域长度或高度的一半
///
float extents = 0;
Vector2 SR_size = Vector2.zero;//SrollRect的尺寸
Vector3[] conners = new Vector3[4];//ScrollRect四角的世界坐标
Vector2 startPos;//ScrollRect的初始位置
///
/// 是否隐藏裁剪部分
///
public bool cullContent = true;
///
/// 将已有的对象初始化一下.
///
public void SetData()
{
for (int i = 0; i < mChild.Count; i++)
{
Transform temp = mChild[i];
UpdateItem(temp, i, i);
}
}
///
/// 加载动画
///
///
///
///
private void Dotween(Transform temp, Vector3 destPos, int i)
{
Tweener tweener = null;
RectTransform panelTransform = temp.GetComponent();
temp.localPosition = new Vector3(destPos.x, -cellHeight * 5, 0);
tweener = panelTransform.DOLocalMove(destPos, 0.3f);
tweener.SetEase(Ease.Linear);//动画曲线
tweener.SetDelay(i * 0.01f);
}
///
/// 实例化预设对象 、添加实例化对象到指定的子对象下
///
/// 元素预制物体
/// 父节点
/// 新创建的元素对象
private GameObject addChild(GameObject goPrefab, Transform parent)
{
if (goPrefab == null || parent == null)
{
LogHelper.LogError("异常。UIWarpContent addChild(goPrefab = null || parent = null)");
return null;
}
GameObject goChild = GameObject.Instantiate(goPrefab) as GameObject;
goChild.transform.SetParent(parent, false);
goChild.SetActive(true);
return goChild;
}
public void Init()
{
for (int i = 0; i < mMinNum; i++)
{
addChild(goItemPrefab, content);
}
}
///
/// 开始函数,将动画放到这里,每当第一次运行会显示动画.
///
void Start()
{
InitList();
}
///
/// 初始化mChild链表
///
void InitList()
{
int i, ChildCount;
InitValue();
mChild.Clear();
for (i = 0, ChildCount = mTrans.childCount; i < ChildCount; i++)
mChild.Add(mTrans.GetChild(i));
////动画放到下面这个函数里
ResetChildPosition();
// LogHelper.Log(mTrans.localPosition.y + " " + startPos.y + " " + cellHeight);
if (mTrans.localPosition.y > 2 * cellHeight && mTrans.localPosition.y<6 *cellHeight)
{
mTrans.localPosition = new Vector3(startPos.x, startPos.y - 3*cellHeight, 0);
}
}
void InitValue()
{
if (viewCount <= 0)
viewCount = 1;
if (minIndex > maxIndex) minIndex = maxIndex;
mTrans = transform;
mRTrans = transform.GetComponent();
mScroll = transform.parent.GetComponent();
mHorizontal = mScroll.horizontal;
SR_size = transform.parent.GetComponent().rect.size;
//四角坐标 横着数
conners[0] = new Vector3(-SR_size.x / 2f, SR_size.y / 2f, 0);
conners[1] = new Vector3(SR_size.x / 2f, SR_size.y / 2f, 0);
conners[2] = new Vector3(-SR_size.x / 2f, -SR_size.y / 2f, 0);
conners[3] = new Vector3(SR_size.x / 2f, -SR_size.y / 2f, 0);
for (int i = 0; i < 4; i++)
{
Vector3 temp = transform.parent.TransformPoint(conners[i]);
conners[i].x = temp.x;
conners[i].y = temp.y;
}
mRTrans.pivot = new Vector2(0, 1);//设置panel的中心在左上角
mScroll.onValueChanged.AddListener(delegate { WrapContent(); });//添加滚动事件回调
startPos = mTrans.localPosition;
}
//初始化各Item的坐标
[ContextMenu("RePosition")]
public virtual void RePosition()
{
InitList();
}
void Update()
{
if (Application.isPlaying) enabled = false;
RePosition();
}
void ResetChildPosition()
{
int rows = 1, cols = 1;
Vector2 startAxis = new Vector2(cellWidth / 10f, -cellHeight / 10f);//起始位置
int i;
int imax = mChild.Count;//Item元素数量
//初始化行列数
if (arrangeType == Arrangement.Vertical) //垂直排列 则适应行数
{
rows = viewCount;
cols = (int)Mathf.Ceil((float)imax / (float)rows);
extents = (float)(cols * cellWidth) * 0.5f;
}
else if (arrangeType == Arrangement.Horizontal) //水平排列则适应列数
{
cols = viewCount;
rows = (int)Mathf.Ceil((float)imax / (float)cols);
extents = (float)(rows * cellHeight) * 0.5f;
}
for (i = 0; i < imax; i++)
{
Transform temp = mChild[i];
int x = 0, y = 0;//行列号
if (arrangeType == Arrangement.Horizontal) { x = i / cols; y = i % cols; }
else if (arrangeType == Arrangement.Vertical) { x = i % rows; y = i / rows; }
Vector3 destPos = new Vector3(startAxis.x + y * cellWidth, startAxis.y - x * cellHeight, 0);
////动画显示,缓动到目的位置;
//if (arrangeType == Arrangement.Vertical)
//{
// if (mRTrans.sizeDelta != new Vector2(destPos.x + cellWidth, viewCount * cellHeight))
// {
// Dotween(temp, destPos, i);
// }
// else
// {
// temp.localPosition = destPos;
// }
//}
//else
//{
// if (mRTrans.sizeDelta != new Vector2(viewCount * cellWidth, -destPos.y + cellHeight))
// {
// Dotween(temp, destPos, i);
// }
// else
// {
// temp.localPosition = destPos;
// }
//}
temp.localPosition = destPos;
//
if (minIndex == maxIndex || (i >= minIndex && i <= maxIndex))
{
cullContent = true;
temp.gameObject.SetActive(true);
UpdateRectsize(temp.localPosition);//更新panel的尺寸
mTrans.localPosition = startPos;
UpdateItem(temp, i, i);
// Dotween(temp, destPos, i);
}
else cullContent = temp.gameObject.activeInHierarchy;//如果预制Item数超过maxIndex则将超过部分隐藏 并 设置cullCintent为ufalse 并且不再更新 panel尺寸
}
}
///
/// 更新panel的尺寸
///
///
void UpdateRectsize(Vector2 pos)
{
if (arrangeType == Arrangement.Vertical)
{
mRTrans.sizeDelta = new Vector2(pos.x + cellWidth, viewCount * cellHeight);
}
else
{
mRTrans.sizeDelta = new Vector2(viewCount * cellWidth, -pos.y + cellHeight);
}
}
int getRealIndex(Vector2 pos)//计算realindex
{
int x = (int)Mathf.Ceil(-pos.y / cellHeight) - 1;//行号
int y = (int)Mathf.Ceil(pos.x / cellWidth) - 1;//列号
int realIndex;
if (arrangeType == Arrangement.Horizontal) realIndex = x * viewCount + y;
else realIndex = x + viewCount * y;
return realIndex;
}
void WrapContent()
{
// LogHelper.Log("ffdds");
Vector3[] conner_local = new Vector3[4];
for (int i = 0; i < 4; i++)
{
conner_local[i] = mTrans.InverseTransformPoint(conners[i]);
}
//计算ScrollRect的中心坐标 相对于this的坐标
Vector2 center = (conner_local[3] + conner_local[0]) / 2f;
if (mHorizontal)
{
float min = conner_local[0].x - cellWidth;//显示区域
float max = conner_local[3].x + cellWidth;
for (int i = 0, imax = mChild.Count; i < imax; i++)
{
Transform temp = mChild[i];
float distance = temp.localPosition.x - center.x;
if (distance < -extents)
{
Vector2 pos = temp.localPosition;
pos.x += extents * 2f;
int realIndex = getRealIndex(pos);
if (minIndex == maxIndex || (realIndex >= minIndex && realIndex < maxIndex))
{
UpdateRectsize(pos);
temp.localPosition = pos;
//设置Item内容
UpdateItem(temp, i, realIndex);
}
}
if (distance > extents)
{
Vector2 pos = temp.localPosition;
pos.x -= extents * 2f;
int realIndex = getRealIndex(pos);
if (minIndex == maxIndex || (realIndex >= minIndex && realIndex < maxIndex))
{
temp.localPosition = pos;
//设置Item内容
UpdateItem(temp, i, realIndex);
}
}
if (cullContent)//设置裁剪部分是否隐藏
{
Vector2 pos = temp.localPosition;
temp.gameObject.SetActive((pos.x > min && pos.x < max) ? true : false);
}
}
}
else
{
float min = conner_local[3].y - cellHeight;//显示区域
float max = conner_local[0].y + cellHeight;
for (int i = 0, imax = mChild.Count; i < imax; i++)
{
Transform temp = mChild[i];
float distance = temp.localPosition.y - center.y;
if (distance < -extents)
{
Vector2 pos = temp.localPosition;
pos.y += extents * 2f;
int realIndex = getRealIndex(pos);
if (minIndex == maxIndex || (realIndex >= minIndex && realIndex < maxIndex))
{
temp.localPosition = pos;
//设置Item内容
UpdateItem(temp, i, realIndex);
}
}
if (distance > extents)
{
Vector2 pos = temp.localPosition;
pos.y -= extents * 2f;
int x = (int)Mathf.Ceil(-pos.y / cellHeight) - 1;//行号
int y = (int)Mathf.Ceil(pos.x / cellWidth) - 1;//列号
int realIndex;
if (arrangeType == Arrangement.Horizontal) realIndex = x * viewCount + y;
else realIndex = x + viewCount * y;
if (minIndex == maxIndex || (realIndex >= minIndex && realIndex < maxIndex))
{
UpdateRectsize(pos);
temp.localPosition = pos;
//设置Item内容
UpdateItem(temp, i, realIndex);
}
}
if (cullContent)//设置裁剪部分是否隐藏
{
Vector2 pos = temp.localPosition;
temp.gameObject.SetActive((pos.y > min && pos.y < max) ? true : false);
}
}
}
}
void UpdateItem(Transform item, int index, int realIndex)
{
// LogHelper.Log(item + "----"+index +"----"+realIndex);
if (onInitializeItem != null)
{
onInitializeItem(item.gameObject, index, realIndex);
}
}
}