美文网首页Unity UGUI 界面 小工具
[Unity3D]ScrollView Item循环利用

[Unity3D]ScrollView Item循环利用

作者: 煎蛋的少年 | 来源:发表于2017-10-24 18:54 被阅读0次

先上Unity里面的组件的详情

Paste_Image.png Paste_Image.png Paste_Image.png Paste_Image.png

接着是代码

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

public class MyScrollViewControllerB : MonoBehaviour
{
          #region Demo贪方便,从编辑上拖上来的物体//

          //滚动的ScrollView//
          public ScrollRect _scrollRect;
          //Mask蒙板,目标是显示区域内的Item,避免在更换Item位置的时候造成直接的视觉误差//
          public RectTransform _viewRect;
          //ScrollView里的Content//
          public RectTransform _content;
          //预设的物体//
          public Item _item;

          #endregion

          //预期想要出现的行数//
          public int _itemAllRowCount = 100;
          //蒙板作用下,上下缓冲的行数//
          public int _hideRowCount = 2;
          //预期要出现的列数//
          public int _columnMax = 3;
          //蒙板作用下,显示的最大行数//
          int _showRowCount;

          //物体的padding//
          public RectOffset _itemPadding;
          //Content的padding//
          public RectOffset _contentPadding;

          //字典,记录每一行对应的Item或者ItemList//
          Dictionary<int , List<Item>> _dictToShowingItem = new Dictionary<int, List<Item>> ();
          //保存从字典中移除的Item//
          List<Item> tempItemList = new List<Item> ();
          //Item的宽和高//
          Vector2 _itemSize;

          // Use this for initialization
          void Start ()
          {
                   
                   //初始化获取Item的宽和高//
                   _itemSize = _item.GetComponent<RectTransform> ().sizeDelta;
                   _itemSize.x += (_itemPadding.left + _itemPadding.right);
                   _itemSize.y += (_itemPadding.top + _itemPadding.bottom);
                   //根据Item的高度和蒙板的高度,确定可视范围内的最大Item行数//
                   _showRowCount = Mathf.CeilToInt (_viewRect.sizeDelta.y / _itemSize.y);
                   //根据预期出现的行数设置Conten的大小//
                   _content.sizeDelta = new Vector2 (_content.sizeDelta.x, _itemSize.y * _itemAllRowCount);
                   //添加滚动监听事件//
                   _scrollRect.onValueChanged.AddListener (OnScrollRectValueChange);

                   //
                   int initRowCount = _itemAllRowCount > (_showRowCount + _hideRowCount * 2) ? (_showRowCount + _hideRowCount * 2) : _itemAllRowCount;
                   for (int rowIndex = 1; rowIndex <= (initRowCount); rowIndex++) {
                             List<Item> tempList = new List<Item> ();
                             for (int columnIndex = 0; columnIndex < _columnMax; columnIndex++) {
                                      Item tempItem = Instantiate (_item, _content) as Item;
                                      tempItem._text.text = ((rowIndex - 1) * _columnMax + columnIndex).ToString ();
                                      tempItem.GetComponent<RectTransform> ().anchoredPosition = new Vector2 ((columnIndex - ((_columnMax - 1) / 2f)) * _itemSize.x, -rowIndex * _itemSize.y);
                                      tempList.Add (tempItem);
                             }
                             _dictToShowingItem.Add (rowIndex, tempList);
                   }
                   foreach (int key in _dictToShowingItem.Keys) {
                             Debug.Log ("------------------ key = " + key);
                   }
                   lastIndex = 0;
          }

          void OnScrollRectValueChange (Vector2 vect)
          {
                   if (_content.anchoredPosition.y < 0 || _content.anchoredPosition.y > _content.sizeDelta.y - _viewRect.sizeDelta.y) {
                             Debug.Log ("超出范围了,不变化!");
                             return;
                   }
                   int index = Mathf.CeilToInt (_content.anchoredPosition.y / _itemSize.y);
                   this.OnItemListChange (index);
          }

          //上一次滚动的Index//
          int lastIndex;
          //传入当前Content位置所代表的Index,去看Content的RectTransform吧//
          void OnItemListChange (int index)
          {
                   if (lastIndex == index)
                             return;
                   Debug.Log ("index = " + index);
                   int minIndex = (index - _hideRowCount);
                   //必须要减 1 ,是因为index自身占用了一行//
                   int maxIndex = (index + _hideRowCount + _showRowCount - 1);
                   if (lastIndex < index) {
                             Debug.Log ("往上移动!");
                             //因为是往上移动,所以先移除上方不需要的Item,移除的个数的话,视情况吧,一般来说两倍的缓冲行数应该可以了//
                             for (int key = minIndex - (_hideRowCount * 2 + _showRowCount); key < minIndex; key++) {
                                      if (_dictToShowingItem.ContainsKey (key)) {
                                                List<Item> tempItems = null;
                                                _dictToShowingItem.TryGetValue (key, out tempItems);
                                                _dictToShowingItem.Remove (key);
                                                for (int i = 0; i < tempItems.Count; i++) {
                                                          tempItemList.Add (tempItems [i]);
                                                }
                                                Debug.Log ("tempItemList.cout = " + tempItemList.Count);
                                      }  else {
                                                Debug.Log ("key = " + key + " 不存在!");
                                      }
                             }

                             //移除完毕后,添加下方需要增加的Item//
                             for (int rowIndex = minIndex; rowIndex < maxIndex; rowIndex++) {
                                      if (rowIndex <= 0 || rowIndex > _itemAllRowCount)
                                                return;
                                      if (!_dictToShowingItem.ContainsKey (rowIndex)) {
                                                Debug.Log ("改变ITem的位置");
                                                List<Item> tempItems = new List<Item> ();
                                                for (int columnIndex = 0; columnIndex < _columnMax; columnIndex++) {
                                                          if (tempItemList.Count == 0) {
                                                                   Debug.Log ("实例化的Item不够用了!!");
                                                                   tempItemList.Add (Instantiate (_item, _content) as Item);
                                                          }
                                                          Item tempItem = tempItemList [0];
                                                          tempItem._text.text = ((rowIndex - 1) * _columnMax + columnIndex).ToString ();
                                                          tempItem.GetComponent<RectTransform> ().anchoredPosition = new Vector2 ((columnIndex - ((_columnMax - 1) / 2f)) * _itemSize.x, -rowIndex * _itemSize.y);
                                                          tempItems.Add (tempItem);
                                                          tempItemList.RemoveAt (0);
                                                }
                                                _dictToShowingItem.Add (rowIndex, tempItems);
                                      }
                             }

                   }  else {
                             //和往上移动类似的//
                             Debug.Log ("往下移动!");
                             //区别在这里,for循环//
                             for (int key = maxIndex + (_hideRowCount * 2); key > maxIndex; key--) {
                                      if (_dictToShowingItem.ContainsKey (key)) {
                                                List<Item> tempItems = null;
                                                _dictToShowingItem.TryGetValue (key, out tempItems);
                                                _dictToShowingItem.Remove (key);
                                                for (int i = 0; i < tempItems.Count; i++) {
                                                          tempItemList.Add (tempItems [i]);
                                                }
                                                Debug.Log ("tempItemList.cout = " + tempItemList.Count);
                                      }  else {
                                                Debug.Log ("key = " + key + " 不存在!");
                                      }
                             }

                             //区别在这里,for循环//
                             for (int rowIndex = maxIndex; rowIndex > minIndex; rowIndex--) {
                                      if (rowIndex <= 0 || rowIndex > _itemAllRowCount)
                                                return;
                                      if (!_dictToShowingItem.ContainsKey (rowIndex)) {
                                                Debug.Log ("改变ITem的位置");
                                                List<Item> tempItems = new List<Item> ();
                                                for (int columnIndex = 0; columnIndex < _columnMax; columnIndex++) {
                                                          if (tempItemList.Count == 0) {
                                                                   Debug.Log ("实例化的Item不够用了!!");
                                                                   tempItemList.Add (Instantiate (_item, _content) as Item);
                                                          }
                                                          Item tempItem = tempItemList [0];
                                                          tempItem._text.text = ((rowIndex - 1) * _columnMax + columnIndex).ToString ();
                                                          tempItem.GetComponent<RectTransform> ().anchoredPosition = new Vector2 ((columnIndex - ((_columnMax - 1) / 2f)) * _itemSize.x, -rowIndex * _itemSize.y);
                                                          tempItems.Add (tempItem);
                                                          tempItemList.RemoveAt (0);
                                                }
                                                _dictToShowingItem.Add (rowIndex, tempItems);
                                      }
                             }
                   }
                   lastIndex = index;
          }
}

Item的代码很简单,就是把Item的Text暴露出来就好,用于观察的。

暂时就这样,还没实际应用过,不过在demo里测了,感觉还行。

相关文章

网友评论

    本文标题:[Unity3D]ScrollView Item循环利用

    本文链接:https://www.haomeiwen.com/subject/tfpxpxtx.html