【NGUI】循环Scroll View
NGUI版本
本文使用的NGUI版本为3.0.9 f4。
脚本作用
此脚本的主要作用是使用10个甚至更少的item来模拟成百上千的item数据。在滑动过程中,当滑到Scroll View的最后面时,会将第一个item拿过来补位,此时需要正确设置补位item的数据;同理,当滑到最前面时,会用最后面的那个item过来补位。
实现方法
1. 脚本放置位置
将脚本放置在Scroll View下面的UIGrid的物体上。
2. UIScrollView设置
取消勾选UIScrollView的Restrict Within Panel选项。
3. UIPanel设置
勾选Scroll View上面的UIPanel的Cull选项。
4. Item设置
为每一个Item都添加一个UIWidget组件,并使用其Visiable属性将其调整到合适的大小。
5. 内容更新
本文仅提供实现循环Scroll View的思路,具体每个Item的内容更新等细节需要开发者自行研究。
6. 问题反馈
如果在实现过程中遇到问题,可以加群进行询问。
附代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[RequireComponent(typeof(UIGrid))]
public class SZUILoopScrollView : MonoBehaviour {
// 前缀字符串,用于命名Item
public string perfix = string.Empty;
// 存储所有Item的UIWidget组件
private List<UIWidget> itemList = new List<UIWidget>();
// 位置参数,包含单元格宽度、高度以及排列方向信息
private Vector4 posParam;
// 缓存当前物体的Transform组件
private Transform cachedTransform;
void Awake() {
// 缓存当前物体的Transform组件
cachedTransform = this.transform;
// 获取UIGrid组件
UIGrid grid = this.GetComponent<UIGrid>();
// 获取单元格的宽度
float cellWidth = grid.cellWidth;
// 获取单元格的高度
float cellHeight = grid.cellHeight;
// 根据UIGrid的排列方式设置位置参数
posParam = new Vector4(cellWidth, cellHeight,
grid.arrangement == UIGrid.Arrangement.Horizontal ? 1 : 0,
grid.arrangement == UIGrid.Arrangement.Vertical ? 1 : 0);
}
void Start() {
// 遍历所有子物体
for (int i = 0; i < cachedTransform.childCount; ++i) {
// 获取子物体的Transform组件
Transform t = cachedTransform.GetChild(i);
// 获取子物体的UIWidget组件
UIWidget uiw = t.GetComponent<UIWidget>();
// 为UIWidget组件命名
uiw.name = string.Format("{0}_{1:D3}", perfix, itemList.Count);
// 将UIWidget组件添加到列表中
itemList.Add(uiw);
}
}
void LateUpdate() {
// 确保至少有两个Item
if (itemList.Count > 1) {
int sourceIndex = -1;
int targetIndex = -1;
int sign = 0;
// 判断第一个Item是否可见
bool firstVislable = itemList[0].isVisible;
// 判断最后一个Item是否可见
bool lastVislable = itemList[itemList.Count - 1].isVisible;
// 如果第一个和最后一个Item的可见性相同,则不进行处理
if (firstVislable == lastVislable) {
return;
}
if (firstVislable) {
// 如果第一个Item可见,将最后一个Item移动到第一个位置
sourceIndex = itemList.Count - 1;
targetIndex = 0;
sign = -1;
} else if (lastVislable) {
// 如果最后一个Item可见,将第一个Item移动到最后一个位置
sourceIndex = 0;
targetIndex = itemList.Count - 1;
sign = 1;
}
// 如果需要移动Item
if (sourceIndex > -1) {
// 获取需要移动的UIWidget组件
UIWidget movedWidget = itemList[sourceIndex];
// 计算移动的偏移量
Vector3 offset = new Vector3(sign * posParam.x * posParam.z, sign * posParam.y * posParam.w, 0);
// 设置移动后的位置
movedWidget.cachedTransform.localPosition = itemList[targetIndex].cachedTransform.localPosition + offset;
// 从列表中移除需要移动的Item
itemList.RemoveAt(sourceIndex);
// 将移动的Item插入到目标位置
itemList.Insert(targetIndex, movedWidget);
}
}
}
}