unity UIScrollView覆用

两个脚本,分别放在ScrollView和content下的item上
UIScroll
利用content的位置来计算item的index,用ScrollRect.onValueChanged.AddListener(action)来监听滑动,然后进行相关计算。

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

public class UIScroll : MonoBehaviour
{
    public enum Direction
    {
        Horizontal,
        Vertical,
    }

    public Direction direction;

    public Vector2 cellSize;
    public Vector2 spacing;

    private Action<UIScrolItem, int> updateAction;

    private RectTransform rectTransform;
    private ScrollRect scrollRect;
    private RectTransform content;
    private float contentWidth;
    private float contentHeight;
    private Vector2 contentOriginalSize;

    private float itemWidth;
    private float itemHeight;
    private int columnCount;
    private int rowCount;

    private int createCount;
    private int listCount;
    private int showCount;

    private int columnSum;
    private int rowSum;

    private int startIndex = 0;
    private int endIndex = 0;
    private int lastStartIndex=0;

    private Dictionary<int, Transform> itemIndexDict = new Dictionary<int, Transform>();

    private void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
        scrollRect = GetComponent<ScrollRect>();
        
        content = transform.Find("Viewport/Content").GetComponent<RectTransform>();
        contentOriginalSize = content.sizeDelta;
    }

    private void OnEnable()
    {
        scrollRect.onValueChanged.AddListener(OnValueChanged);
    }

    public void init(int count)
    {
        startIndex = endIndex = lastStartIndex = 0;

        itemWidth = cellSize.x;
        itemHeight = cellSize.y;
        
        if (columnCount <= 0)
            columnCount = (int)(contentOriginalSize.x / (itemWidth+spacing.x));
        if (rowCount <= 0)
            rowCount = (int)(contentOriginalSize.y / (itemHeight+spacing .y));

        InitData();
        InitList(count);
    }

    private void InitData()
    {
        if(direction==Direction.Horizontal)
        {
            scrollRect.horizontal = true;
            scrollRect.vertical = false;
        }
        else
        {
            scrollRect.horizontal = false;
            scrollRect.vertical = true;
        }

        foreach (Transform item in content.transform)
        {
            UIScrolItem cell = item.GetComponent<UIScrolItem>();
            if (cell.GetItem() != null)
            {

            }
            cell.SetItem(null);
        }

        content.pivot =
            content.anchorMin =
            content.anchorMax = new Vector2(0, 1);
        content.sizeDelta = contentOriginalSize;
        content.anchoredPosition = Vector2.zero;
        columnCount = (int)(contentOriginalSize.x / (itemWidth + spacing.x));
        rowCount = (int)(contentOriginalSize.y / (itemHeight + spacing.y));
        int c = columnCount;
        int r = rowCount;
        if (direction == Direction.Horizontal)
            c += 2;
        else r += 2;
        createCount = c * r;

    }

    private void InitList(int count)
    {
        listCount = count;
        content.transform.localPosition = Vector2.zero;
        if(direction == Direction.Horizontal)
        {
            columnSum = count / rowCount + count % rowCount == 0 ? 0 : 1;
            contentWidth = columnSum * itemWidth + (columnSum - 1) * spacing.x;
            contentHeight = rowCount * itemHeight + (rowCount - 1) * spacing.y;
        }
        else
        {
            rowSum = (count / columnCount) + (count % columnCount == 0 ? 0 : 1); 
            contentWidth = columnCount * itemWidth + (columnCount - 1) * spacing.x;
            contentHeight = rowSum * itemHeight + (rowSum - 1) * spacing.y;
        }

        content.sizeDelta = new Vector2(contentWidth, contentHeight);
        startIndex = 0;
        showCount = Math.Min(createCount, count);
        itemIndexDict.Clear();

        for(int i=0;i<showCount;i++)
        {
            Transform item = GetItem(i);
            SetItem(item,i);
        }
    }

    public Transform GetItem(int index)
    {
        Transform item = null;
        if(index<content.childCount)
        {
            item = content.GetChild(index);
        }
        else
        {
            var go = new GameObject(index.ToString(), typeof(UIScrolItem));
            var uiScrollItem = go.GetComponent<UIScrolItem>();
            uiScrollItem.init(itemWidth, itemHeight);
            go.transform.SetParent(content);
            item = go.transform;
        }
        item.name = index.ToString();
        item.SetParent(content);
        item.localPosition = Vector3.one;
        return item;
    }

    public void SetItem(Transform item,int index)
    {
        item.localPosition = GetPos(index);
        item.name = index.ToString();
        item.SetParent(content);
        itemIndexDict.Add(index, item);
        Debug.Log("向itemIndexDict中添加" + index.ToString());

    }

    public Vector2 GetPos(int index)
    {
        if (direction == Direction.Horizontal)
            return GetPosH(index);
        else return GetPosV(index);
    }

    public Vector2 GetPosH(int index)
    {
        Vector2 v = new  Vector2(index / rowCount * (itemWidth + spacing.x), ((((index + 1) % rowCount) == 0 ? rowCount : ((index + 1) % rowCount)) - 1) * (itemHeight + spacing.y));
        return v;
    }

    public Vector2 GetPosV(int index)
    {
        Vector2 v = new Vector2(((((index + 1) % columnCount) == 0 ? columnCount : ((index + 1) % columnCount))-1) * (itemWidth + spacing.x), -index / columnCount * (itemHeight + spacing.y));
        return v;
    }

    private List<int> newIndexList = new List<int>();
    private List<int> changedIndexList = new List<int>();
    Vector2 _pos;
    public void OnValueChanged(Vector2 pos)
    {
        _pos = pos;
        if (listCount < createCount)
            return;

        startIndex = GetStartIndex(content.localPosition);

        if (startIndex + createCount > listCount)
        {
            startIndex = listCount - createCount;
            endIndex = listCount - 1;
        }
        else endIndex = startIndex + createCount - 1;

        if (startIndex == lastStartIndex)
            return;

        lastStartIndex = startIndex;

        newIndexList.Clear();
        changedIndexList.Clear();
        for(int i=startIndex;i<=endIndex;i++)
        {
            newIndexList.Add(i);
            Debug.Log("向newIndexList中添加" + i);
        }

        var itr = itemIndexDict.GetEnumerator();
        while(itr.MoveNext())
        {
            int idx = itr.Current.Key;
            if(idx>=startIndex && idx<=endIndex)
            {
                if (newIndexList.Contains(idx))
                {
                    newIndexList.Remove(idx);
                    Debug.Log("从newIndexList中删除" + idx);
                }
                continue;
            }
            else
            {
                changedIndexList.Add(idx);
            }
        }

        for(int i=0;i<newIndexList.Count && i<changedIndexList.Count;i++)
        {
            int newIndex = newIndexList[i];
            int oldIndex = changedIndexList[i];
            if(newIndex >= 0 && newIndex < listCount)
            {
                var item = itemIndexDict[oldIndex];
                itemIndexDict.Remove(oldIndex);
                SetItem(item, newIndex);
            }
        }

    }

    public int GetStartIndex(Vector2 v)
    {
        if (direction == Direction.Horizontal)
            return GetStartIndexH(v.x);
        else
            return GetStartIndexV(v.y);
    }

    public int GetStartIndexH(float x)
    {
        x = -x;
        if (x < itemWidth)
            return 0;
        float scrollWidth = rectTransform.sizeDelta.x;
        if(x>(content.sizeDelta.x - scrollWidth))
        {
            if (listCount < createCount)
                return 0;
            else
                return listCount - createCount;
        }

        return (int)(x / (itemWidth + spacing.x)) * rowCount + ((x % (itemWidth + spacing.x)) > 0 ? 1 : 0) - 1;
        
    }

    public int GetStartIndexV(float y)
    {
        if (y < itemHeight)
            return 0;

        float scrollHeight = rectTransform.sizeDelta.y;
        if(y>(content.sizeDelta.y - scrollHeight))
        {
            if (listCount < createCount)
                return 0;
            else
                return listCount - createCount;
        }

        return (int)(y / (itemHeight + spacing.y)) * columnCount + ((y % (itemHeight + spacing.y)) > 0 ? 1 : 0 )-1;

    }


}

UIScrolItem

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

[RequireComponent(typeof(RectTransform),typeof(Image))]
public class UIScrolItem : MonoBehaviour
{
    private RectTransform rectTransform;
    private RectTransform item;

    private void Awake()
    {
        rectTransform = GetComponent<RectTransform>();
    }

    public void init(float w,float h)
    {
        rectTransform.pivot =
            rectTransform.anchorMin =
            rectTransform.anchorMax = new Vector2(0, 1);
        rectTransform.sizeDelta = new Vector2(w, h);
    }

    public void SetItem(RectTransform rt)
    {
        if(rt!=item)
        {
            if(rt!=null)
            {
                rt.SetParent(transform);
                rt.localPosition = Vector2.one;
            }
            item = rt;
        }
    }

    public RectTransform GetItem()
    {
        return item;
    }

}

在随便一个按钮上添加一个事件

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

public class MainUi : MonoBehaviour
{
    public Button[] buttons=new Button[3];
    public GameObject scrollView;

    public UIScroll uIScroll;

    public void OnClickBag()
    {
        if(!scrollView.activeInHierarchy)
        {
            scrollView.SetActive(true);
            uIScroll.init(100);

        }
        else
        {
            scrollView.SetActive(false);
        }
    }



}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值