码迷,mamicode.com
首页 > 其他好文 > 详细

UGUI 背包滚动视图(无限滚动)

时间:2015-12-18 12:58:54      阅读:2225      评论:0      收藏:0      [点我收藏+]

标签:

技术分享


=。= 最近负责道具背包系统开发, 主程非要把滚动视图制作成无限滚动这样的话可以节约内存, 其实我想说的是没必要这么恐惧内存,但是需求来了还是照着制作一个,每次滚动的时候刷新对应单元格数据即可.

效果图:

技术分享技术分享

核心代码:

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

UGUI 背包滚动视图(无限滚动)

标签:

原文地址:http://www.cnblogs.com/plateFace/p/5056626.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!