[Unity3d][NGUI]自写循环UIScrollView组件. 使用少量Item循环使用.

本组件根据四爷和Aklan的脚本为基础写的.

转载请注明出处:http://blog.csdn.net/zxsean/article/details/37386413


本组件使用时挂载在ScrollView下的Grid上即可.Item的数量只需要能覆盖一个页面的数量就可以了.


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

/// <summary>
/// Loop循环ScrollView
/// 使用的时候挂载在ScrollView下面的UIGrid上就可以了
/// 然后UIGrid下面放置部分Item即可实现循环Item
/// </summary>
[RequireComponent(typeof(UIGrid))]
public class LoopScrollView_ZX : MonoBehaviour
{
    #region Members

    /// <summary>
    /// 存储物件列表
    /// </summary>
    private List<UIWidget> m_itemList = new List<UIWidget>();

    private Vector4 m_posParam;
    private Transform m_cachedTransform;

    /// <summary>
    /// 起始下标
    /// </summary>
    private int m_startIndex;
    /// <summary>
    /// 最大长度
    /// </summary>
    private int m_MaxCount;

    /// <summary>
    /// 物件刷新代理事件
    /// </summary>
    /// <param name="go"></param>
    public delegate void OnItemChange(GameObject go);
    private OnItemChange m_pItemChangeCallBack;

    /// <summary>
    /// item点击代理事件
    /// </summary>
    /// <param name="go"></param>
    /// <param name="i"></param>
    public delegate void OnClickItem(GameObject go, int i);
    private OnClickItem m_pOnClickItemCallBack;

    /// <summary>
    /// 父ScrollView
    /// </summary>
    public UIScrollView m_scrollView;

    #endregion

    void Awake()
    {
        m_cachedTransform = this.transform;
        m_scrollView = m_cachedTransform.parent.GetComponent<UIScrollView>();

        // 设置Cull
        m_scrollView.GetComponent<UIPanel>().cullWhileDragging = true;

        UIGrid _grid = this.GetComponent<UIGrid>();
        float _cellWidth = _grid.cellWidth;
        float _cellHeight = _grid.cellHeight;
        m_posParam = new Vector4(_cellWidth,
                                                    _cellHeight,
                                                    _grid.arrangement == UIGrid.Arrangement.Horizontal ? 1 : 0,
                                                    _grid.arrangement == UIGrid.Arrangement.Vertical ? 1 : 0);
    }

    /// <summary>
    /// 初始化表
    /// </summary>
    public void Init(bool _clickItem)
    {
        m_itemList.Clear();

        for (int i = 0; i < m_cachedTransform.childCount; ++i)
        {
            Transform _t = m_cachedTransform.GetChild(i);
            UIWidget uiW = _t.GetComponent<UIWidget>();
            if (uiW == null)
            {
                uiW = _t.gameObject.AddComponent<UIWidget>();
            }
            uiW.name = m_itemList.Count.ToString();
            m_itemList.Add(uiW);

            // 允许响应点击事件
            if (_clickItem)
            {
                // 碰撞
                BoxCollider _c = _t.GetComponent<BoxCollider>();
                if (_c == null)
                {
                    _c = _t.gameObject.AddComponent<BoxCollider>();
                    uiW.autoResizeBoxCollider = true;
                }

                // 事件接收
                UIEventListener _listener = _t.GetComponent<UIEventListener>();
                if (_listener == null)
                {
                    _listener = _t.gameObject.AddComponent<UIEventListener>();
                }

                // 点击回调
                _listener.onClick = OnClickListItem;
            }
        }
    }

    /// <summary>
    /// 更新表单
    /// </summary>
    /// <param name="_count">数量</param>
    public void UpdateListItem(int _count)
    {
        m_startIndex = 0;
        m_MaxCount = _count;

        for (int i = 0; i < m_itemList.Count; i++)
        {
            UIWidget _item = m_itemList[i];
            _item.name = i.ToString();
            _item.Invalidate(true);

            NGUITools.SetActive(_item.gameObject, i < _count);
        }
    }

    public List<UIWidget> GetItemList()
    {
        return m_itemList;
    }

    public List<T> GetItemList<T>() where T : Component
    {
        List<T> _list = new List<T>();

        foreach (UIWidget _wd in m_itemList)
        {
            _list.Add(_wd.GetComponent<T>());
        }

        return _list;
    }

    public List<T> GetItemListInChildren<T>() where T : Component
    {
        List<T> _list = new List<T>();

        foreach (UIWidget _wd in m_itemList)
        {
            _list.Add(_wd.GetComponentInChildren<T>());
        }

        return _list;
    }

    void LateUpdate()
    {
        if (m_itemList.Count <= 1)
        {
            return;
        }

        int _sourceIndex = -1;
        int _targetIndex = -1;
        int _sign = 0;

        bool firstVislable = m_itemList[0].isVisible;
        bool lastVisiable = m_itemList[m_itemList.Count - 1].isVisible;

        // 如果都显示,那么返回
        if (firstVislable == lastVisiable)
        {
            return;
        }

        // 得到需要替换的源和目标
        if (firstVislable)
        {
            _sourceIndex = m_itemList.Count - 1;
            _targetIndex = 0;
            _sign = 1;
        }
        else if (lastVisiable)
        {
            _sourceIndex = 0;
            _targetIndex = m_itemList.Count - 1;
            _sign = -1;
        }

        // 如果小于真正的初始索引或大于真正的结束索引,返回
        int realSourceIndex = int.Parse(m_itemList[_sourceIndex].gameObject.name);
        int realTargetIndex = int.Parse(m_itemList[_targetIndex].gameObject.name);

        if (realTargetIndex <= m_startIndex ||
            realTargetIndex >= (m_MaxCount - 1))
        {
            m_scrollView.restrictWithinPanel = true;
            return;
        }

        m_scrollView.restrictWithinPanel = false;
        UIWidget movedWidget = m_itemList[_sourceIndex];

        Vector3 _offset = new Vector2(_sign * m_posParam.x * m_posParam.z,
                                                       _sign * m_posParam.y * m_posParam.w);

        movedWidget.cachedTransform.localPosition = m_itemList[_targetIndex].cachedTransform.localPosition + _offset;

        m_itemList.RemoveAt(_sourceIndex);
        m_itemList.Insert(_targetIndex, movedWidget);
        movedWidget.name = (realSourceIndex > realTargetIndex ? (realTargetIndex - 1) : (realTargetIndex + 1)).ToString();

        OnItemChangeMsg(movedWidget.gameObject);
    }

    /// <summary>
    /// 设置代理
    /// </summary>
    /// <param name="_onItemChange"></param>
    /// <param name="_onClickItem"></param>
    public void SetDelegate(OnItemChange _onItemChange,
                                         OnClickItem _onClickItem)
    {
        m_pItemChangeCallBack = _onItemChange;

        if (_onClickItem != null)
        {
            m_pOnClickItemCallBack = _onClickItem;
        }
    }

    void OnItemChangeMsg(GameObject go)
    {
        if (m_pItemChangeCallBack != null)
        {
            m_pItemChangeCallBack(go);
        }
    }

    void OnClickListItem(GameObject go)
    {
        int _i = int.Parse(go.name);

        if (m_pOnClickItemCallBack != null)
        {
            m_pOnClickItemCallBack(go, _i);
        }
    }
}

测试脚本.挂载在Grid上即可.

using UnityEngine;
using System.Collections;

/// <summary>
/// 测试脚本
/// </summary>
public class Test : MonoBehaviour
{
    LoopScrollView_ZX m_scrollView;

    void Start()
    {
        m_scrollView = this.GetComponent<LoopScrollView_ZX>();
        m_scrollView.Init(true);
        m_scrollView.UpdateListItem(100);
        m_scrollView.SetDelegate(null, OnClickTest);
    }

    /// <summary>
    /// 点击事件
    /// </summary>
    /// <param name="go"></param>
    /// <param name="i"></param>
    void OnClickTest(GameObject go, int i)
    {
        Debug.Log(go.name + "," + i);
    }
}


评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值