标签:
=。= 最近负责道具背包系统开发, 主程非要把滚动视图制作成无限滚动这样的话可以节约内存, 其实我想说的是没必要这么恐惧内存,但是需求来了还是照着制作一个,每次滚动的时候刷新对应单元格数据即可.
效果图:
核心代码:
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using UnityEngine.EventSystems; [RequireComponent(typeof(ScrollRect))] public class UITableViewControl : MonoBehaviour, IBeginDragHandler, IEndDragHandler { public delegate void UpdateCell(UITableViewControl tv, int idx, GameObject cell); #region 字段 GameObject content; [SerializeField] Vector2 cellSize; [SerializeField] GridLayoutGroup.Axis startAxis = GridLayoutGroup.Axis.Vertical; [SerializeField] GameObject cellTemplate; UpdateCell ucHandler; int cellCount; int activityCellCount; int newIdx; int curIdx; Vector2 scrollViewSize; Dictionary<int, GameObject> activityCells = new Dictionary<int, GameObject>(); List<int> unuseKey = new List<int>(); [SerializeField] bool isPageturn; //是否滑动翻页形式 [SerializeField] private int pageCellCount; //每页的单元格数量 [SerializeField] private int showPageCellCount; //每页显示的单元格数量 private ScrollRect scrollRect; private Vector2 pressPosition; private DirectionEnum direction; private int curPage; private RectTransform contentRect; private Vector2 movePosition; #endregion #region 属性 public int PageColumn { get { return pageCellCount; } set { pageCellCount = value; } } public int CellCount { get { return cellCount; } set { cellCount = value; } } #endregion #region Function void Awake() { content = GetComponent<ScrollRect>().content.gameObject; cellTemplate.SetActive(false); RectTransform rt = cellTemplate.GetComponent<RectTransform>(); rt.anchorMin = rt.anchorMax = new Vector2(0, 1); scrollViewSize = GetComponent<RectTransform>().rect.size; scrollRect = GetComponent<ScrollRect>(); contentRect = content.GetComponent<RectTransform>(); } public void Init(int cellCount,UpdateCell ucHandler, bool bLoadData = true) { this.cellCount = cellCount; this.ucHandler = ucHandler; if (bLoadData) ReloadData(); } public GameObject GetCell(int idx) { if (activityCells.ContainsKey(idx)) return activityCells[idx]; return null; } public void ReloadData() { curIdx = newIdx = 0; List<int> cellKeys = new List<int>(activityCells.Keys); for (int i = 0; i != cellKeys.Count; ++i) { GameObject.Destroy(activityCells[cellKeys[i]]); } activityCells.Clear(); activityCellCount = 0; if (startAxis == GridLayoutGroup.Axis.Vertical) { content.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, scrollViewSize.x); content.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, cellSize.y * cellCount); activityCellCount = cellSize.y * cellCount > scrollViewSize.y ? (int)(scrollViewSize.y / cellSize.y) + 2 : cellCount; } else { content.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, cellSize.x * cellCount); content.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, scrollViewSize.y); activityCellCount = cellSize.x * cellCount > scrollViewSize.x ? (int)(scrollViewSize.x / cellSize.x) + 2 : cellCount; } if (activityCellCount > cellCount) activityCellCount = cellCount; } public void FixedUpdate() { if (activityCellCount <= 0 || activityCells.Count == activityCellCount) return; int idx = activityCells.Count; GameObject go = GameObject.Instantiate(cellTemplate) as GameObject; go.transform.SetParent(content.transform, false); go.name = "Cell" + idx; if (startAxis == GridLayoutGroup.Axis.Vertical) { //go.transform.localPosition = new Vector3(scrollViewSize.x / 2, -idx * cellSize.y - cellSize.y / 2, 0); go.GetComponent<RectTransform>().anchoredPosition = new Vector3(scrollViewSize.x / 2, -idx * cellSize.y - cellSize.y / 2); } else { //go.transform.localPosition = new Vector3(idx * cellSize.x + cellSize.x / 2, -scrollViewSize.y / 2, 0); go.GetComponent<RectTransform>().anchoredPosition = new Vector3(idx * cellSize.x + cellSize.x / 2, -scrollViewSize.y / 2); } go.SetActive(true); activityCells.Add(idx, go); if (ucHandler != null) { ucHandler(this, idx, go); } } public void Update() { if (isPageturn) { if (direction != DirectionEnum.None) { contentRect.anchoredPosition = Vector2.Lerp(contentRect.anchoredPosition, movePosition, 0.1f); if (Vector2.Distance(contentRect.anchoredPosition, movePosition) < 4f) { direction = DirectionEnum.None; scrollRect.StopMovement(); contentRect.anchoredPosition = movePosition; } } } if (activityCells.Count == activityCellCount) { //获取最后一个坐标 if (startAxis == GridLayoutGroup.Axis.Vertical) { newIdx = (int)(contentRect.anchoredPosition.y / cellSize.y); } else { newIdx = (int)(-contentRect.anchoredPosition.x / cellSize.x); } if (newIdx == curIdx) return; if (newIdx < 0) { if (curIdx == 0) return; newIdx = 0; } else if (newIdx > cellCount - activityCellCount) { if (curIdx == cellCount - activityCellCount) return; newIdx = cellCount - activityCellCount; } curIdx = newIdx; foreach (int idx in activityCells.Keys) { if (idx >= newIdx && idx < newIdx + activityCellCount) continue; //方块在区域看不见,加入无用数组中 if (unuseKey.Contains(idx) == false) unuseKey.Add(idx); } for (int i = 0; i != activityCellCount; ++i) { int idx = newIdx + i; if (activityCells.ContainsKey(idx)) continue; GameObject go = activityCells[unuseKey[0]]; activityCells.Remove(unuseKey[0]); activityCells.Add(idx, go); unuseKey.RemoveAt(0); go.name = "Cell" + idx; if (startAxis == GridLayoutGroup.Axis.Vertical) { go.GetComponent<RectTransform>().anchoredPosition = new Vector2(scrollViewSize.x / 2, -idx * cellSize.y - cellSize.y / 2); } else { go.GetComponent<RectTransform>().anchoredPosition = new Vector2(idx * cellSize.x + cellSize.x / 2, -scrollViewSize.y / 2); } if (ucHandler != null) { ucHandler(this, idx, go); } } } } public void OnGUI() { GUILayout.Label("activityCellCount: " + activityCellCount); GUILayout.Label("cellCount: " + cellCount); GUILayout.Label("newIdx: " + newIdx); GUILayout.Label("curIdx: " + curIdx); GUILayout.Label("cellSize.y: " + cellSize.y); GUILayout.Label("移动到距离: " + movePosition); GUILayout.Label("目前距离: " + this.contentRect.anchoredPosition); } #endregion #region Drag事件 public void OnEndDrag(PointerEventData eventData) { if (isPageturn && cellCount > showPageCellCount) { if (startAxis == GridLayoutGroup.Axis.Vertical) { float distance = -(Mathf.Abs(eventData.pressPosition.y) - Mathf.Abs(eventData.position.y)); int moveCellCount = DistanceCalculateMoveCellCount(distance); movePosition = new Vector2(contentRect.anchoredPosition.x, curPage > 0 ? (cellSize.y * moveCellCount) : -(cellSize.y * moveCellCount)); } else if (startAxis == GridLayoutGroup.Axis.Horizontal) { float distance = Mathf.Abs(eventData.pressPosition.x) - Mathf.Abs(eventData.position.x); int moveCellCount = DistanceCalculateMoveCellCount(distance); movePosition = new Vector2(curPage > 0 ? -(cellSize.x * moveCellCount) : (cellSize.x * moveCellCount), contentRect.anchoredPosition.y); } } } private int DistanceCalculateMoveCellCount(float distance) { if (distance > 10f) { direction = DirectionEnum.Font; //(单元格总数 - 页面显示个数 - 当前页数 * 每页翻得单元格子) > 0 , 可以向前滑动 if ((cellCount - showPageCellCount - curPage * pageCellCount) > 0) { curPage += 1; } } else if (distance < -10f) { direction = DirectionEnum.Back; if (curPage > 0) { curPage -= 1; } } //页数 * 每页单元格个数 + 每页显示单元格个数 > 总数 //结果1: 要移动的单元格数量 = 单元格总数 - 显示页面的个数 //结果2: 要移动的单元格数量 = 页数 * 每页单元格个数 return curPage * pageCellCount + showPageCellCount > cellCount ? cellCount - showPageCellCount : curPage * pageCellCount; } public void OnBeginDrag(PointerEventData eventData) { pressPosition = eventData.pressPosition; } #endregion } public enum DirectionEnum { None, Font, Back }
下载地址: http://yunpan.cn/c34ikhZrDefz7 访问密码 8009
标签:
原文地址:http://www.cnblogs.com/plateFace/p/5056626.html