UGUI循环滑动列表

目前只实现上下滑动

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using System;
using System.Linq;

public enum Direction
{
    TopToBottom,//目前只实现
    RightToLeft
}

public delegate void UpdateListItem(Transform item, int index, object data);
[RequireComponent(typeof(ScrollRect), typeof(RectMask2D))]
public class MyScrollList : MonoBehaviour
{

    public GameObject itemPrefab;
    public Direction dir = Direction.TopToBottom;
    public int itemWidth;     //单元格宽  
    public int itemHeight;    //单元格高  

    public int rowCount;
    public int colCount; 
    public int vGap = 0;//垂直间隔
    public int hGap = 0;//水平间隔

    public int paddingTop = 0;
    public int paddingBottom = 0;
    public int paddingLeft = 0;
    public int paddingRight = 0;

    private ScrollRect panel;
    private object[] data;
    private int startIndex;
    private RectTransform content;
    private UpdateListItem m_updateItem;
    private Dictionary<int, Transform> itemDict = new Dictionary<int, Transform>();

    public void OnEnable() //test
    {
        if (Application.isPlaying)
        {
            Init(new object[] { 0,1, 2, 3, 4, 5,6,7,8,9 }, delegate (Transform item, int index, object data)
            {
                item.Find("text").GetComponent<Text>().text = data.ToString();
            });
        }
    }

    // 初始化  
    public void Init(object[] dataList, UpdateListItem updateItem)
    {
        if (itemPrefab == null)
        {
            return;
        }
        data = dataList;
        itemPrefab.SetActive(false);
        m_updateItem = updateItem;
        panel = GetComponent<ScrollRect>();
        switch (dir)
        {
            case Direction.TopToBottom:
                panel.vertical = true;
                panel.horizontal = false;
                break;
            case Direction.RightToLeft:
                panel.vertical = false;
                panel.horizontal = true;
                break;
        }
        if (content == null)
        {
            content = new GameObject("content").AddComponent<RectTransform>();
        }
        content.SetParent(transform);
        content.pivot = new Vector2(0, 1);
        content.anchorMax = content.anchorMin = new Vector2(0, 1);
        int totalNum = Mathf.Max(dataList.Length, colCount * rowCount);
        int totalRow = Mathf.CeilToInt(totalNum / colCount);
        content.sizeDelta = new Vector2(colCount * (itemWidth) + (colCount - 1) * hGap + paddingLeft + paddingRight, totalRow * (itemHeight) + (totalRow - 1) * vGap + paddingBottom + paddingTop) ;
        panel.content = content;
        panel.onValueChanged.AddListener(OnScroll);
        for (int i = 0; i < Mathf.Min(colCount * rowCount, dataList.Length) ; i++)
        {

            Transform item = UpdateItem(i);
            itemDict[i] = item;
        }
        content.localScale = Vector3.one;
        content.anchoredPosition = Vector2.zero;
    }

    private void OnScroll(Vector2 pos)
    {
        int rowIndex = (int)((content.anchoredPosition.y - paddingTop) / (itemHeight + vGap));
        if (startIndex != rowIndex)
        {
            Dictionary<int, Transform> temp = new Dictionary<int, Transform>();
            List<int> emptyIndex = new List<int>();
            List<int> tempIndex = new List<int>();
            for (int i = rowIndex; i < rowIndex + rowCount; i++)
            {
                for (int j = 0; j < colCount; j++)
                {
                    int dataIndex = i * colCount + j;
                    if (itemDict.ContainsKey(dataIndex))
                    {
                        temp.Add(dataIndex, itemDict[dataIndex]);
                        itemDict.Remove(dataIndex);
                    }
                    else
                    {
                        //之前没有显示
                        emptyIndex.Add(dataIndex);
                        tempIndex.Add(dataIndex);
                    }
                    
                }
            }

            //上次显示,这次不用显示,优先把这些item用在这次显示上
            foreach (var item in itemDict.Values)
            {
                var i = tempIndex[0];
                tempIndex.RemoveAt(0);
                temp[i] = item;
            }
            itemDict = temp;
            //需要更新的
            foreach (var i in emptyIndex)
            {
                UpdateItem(i);
            }

            startIndex = rowIndex;
        }
        
    }

    // 创建item或者更新
    private Transform UpdateItem(int index)
    {

        Transform item = null;
        if (!itemDict.TryGetValue(index, out item))
        {
            item = GameObject.Instantiate(itemPrefab).transform;
            var itemRect = item.GetComponent<RectTransform>();
            itemRect.pivot = new Vector2(0, 1);
            itemRect.anchorMax = itemRect.anchorMin = new Vector2(0, 1);
            item.gameObject.SetActive(true);
            item.SetParent(content);
            item.localScale = Vector3.one;
            item.name = index.ToString();
        }
        if (index<0 || index >= data.Length)
        {
            item.gameObject.SetActive(false);
            return item;
        }

        // 1.行  
        int row = index / colCount;
        // 2.列  
        int col = index % colCount;
        item.GetComponent<RectTransform>().anchoredPosition = new Vector2(col * itemWidth + col * hGap + paddingLeft, -1 * row * itemHeight - row * vGap - paddingTop);
        item.gameObject.SetActive(true);
        if (m_updateItem != null)
        {
            m_updateItem(item, index, data[index]);
        }
        return item;
    }
}


编辑器下可视化工具

using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
//预览工具
class GizmoList
{
    [DrawGizmo(GizmoType.Selected | GizmoType.Active)]
    private static void DrawGizmoForMyScrollList(MyScrollList grid, GizmoType gizmoType)
    {
        var gridRect = grid.GetComponent<RectTransform>();
        var itemRect = new Rect(-grid.itemWidth / 2, -grid.itemHeight / 2, grid.itemWidth, grid.itemHeight);

        int count = grid.rowCount * grid.colCount;

        for (int i = 0; i < count; i++)
        {
            int row = i / grid.colCount;
            int col = i % grid.colCount;
            var offset =  new Vector2(col * grid.itemWidth + col * grid.hGap - gridRect.rect.width /2f + 0.5f * grid.itemWidth + grid.paddingLeft, -1 * row * grid.itemHeight - row * grid.vGap + gridRect.rect.width / 2f - 0.5f * grid.itemHeight - grid.paddingTop);
            DrawGizmoRect(gridRect, itemRect, offset, Color.red);
        }
    }

    private static void DrawGizmoRect(RectTransform targetRect, Rect rect, Vector2 offset, Color color)
    {
        var lines = new List<Vector3>()
        {
            new Vector3(rect.xMin, rect.yMin, 0),
            new Vector3(rect.xMin, rect.yMax, 0),
            new Vector3(rect.xMax, rect.yMax, 0),
            new Vector3(rect.xMax, rect.yMin, 0),
            new Vector3(rect.xMin, rect.yMin, 0)
        };

        lines = lines.ConvertAll(a => (targetRect.TransformPoint(a + new Vector3(offset.x, offset.y, 0.0f))));

        Handles.color = color;
        Handles.DrawAAPolyLine(lines.ToArray());
    }
}

演示

UGUI循环滑动列表_第1张图片

你可能感兴趣的:(UGUI扩展,c#,linq,ui)