[+] UI循环列表拓展Grid 用法和List一样

[+] UI循环列表拓展Grid 用法和List一样
This commit is contained in:
ALEXTANG
2023-08-18 16:32:08 +08:00
parent 0e6851e691
commit 0f2ad3c71d
26 changed files with 2868 additions and 41 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0fcee77031f85f84dbc6735c875d64b8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
namespace GameLogic
{
public enum SnapStatus
{
NoTargetSet = 0,
TargetHasSet = 1,
SnapMoving = 2,
SnapMoveFinish = 3
}
public enum ItemCornerEnum
{
LeftBottom = 0,
LeftTop,
RightTop,
RightBottom,
}
public enum ListItemArrangeType
{
TopToBottom = 0,
BottomToTop,
LeftToRight,
RightToLeft,
}
public enum GridItemArrangeType
{
TopLeftToBottomRight = 0,
BottomLeftToTopRight,
TopRightToBottomLeft,
BottomRightToTopLeft,
}
public enum GridFixedType
{
ColumnCountFixed = 0,
RowCountFixed,
}
public struct RowColumnPair
{
public RowColumnPair(int row1, int column1)
{
mRow = row1;
mColumn = column1;
}
public bool Equals(RowColumnPair other)
{
return this.mRow == other.mRow && this.mColumn == other.mColumn;
}
public static bool operator ==(RowColumnPair a, RowColumnPair b)
{
return (a.mRow == b.mRow)&&(a.mColumn == b.mColumn);
}
public static bool operator !=(RowColumnPair a, RowColumnPair b)
{
return (a.mRow != b.mRow) || (a.mColumn != b.mColumn); ;
}
public override int GetHashCode()
{
return 0;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
return (obj is RowColumnPair) && Equals((RowColumnPair)obj);
}
public int mRow;
public int mColumn;
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 19e4e487f35877f4b9bb864eb43484d6
timeCreated: 1534508353
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d7f738dc5a266e94d9e9870fc76009c2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,173 @@
namespace GameLogic
{
//if GridFixedType is GridFixedType.ColumnCountFixed, then the GridItemGroup is one row of the gridview
//if GridFixedType is GridFixedType.RowCountFixed, then the GridItemGroup is one column of the gridview
public class GridItemGroup
{
private int _count = 0;
private int _groupIndex = -1;//the row index or the column index of this group
private LoopGridViewItem _first = null;
private LoopGridViewItem _last = null;
public int Count => _count;
public LoopGridViewItem First => _first;
public LoopGridViewItem Last => _last;
public int GroupIndex
{
get => _groupIndex;
set => _groupIndex = value;
}
public LoopGridViewItem GetItemByColumn(int column)
{
LoopGridViewItem cur = _first;
while(cur != null)
{
if(cur.Column == column)
{
return cur;
}
cur = cur.NextItem;
}
return null;
}
public LoopGridViewItem GetItemByRow(int row)
{
LoopGridViewItem cur = _first;
while (cur != null)
{
if (cur.Row == row)
{
return cur;
}
cur = cur.NextItem;
}
return null;
}
public void ReplaceItem(LoopGridViewItem curItem,LoopGridViewItem newItem)
{
newItem.PrevItem = curItem.PrevItem;
newItem.NextItem = curItem.NextItem;
if(newItem.PrevItem != null)
{
newItem.PrevItem.NextItem = newItem;
}
if(newItem.NextItem != null)
{
newItem.NextItem.PrevItem = newItem;
}
if(_first == curItem)
{
_first = newItem;
}
if(_last == curItem)
{
_last = newItem;
}
}
public void AddFirst(LoopGridViewItem newItem)
{
newItem.PrevItem = null;
newItem.NextItem = null;
if (_first == null)
{
_first = newItem;
_last = newItem;
_first.PrevItem = null;
_first.NextItem = null;
_count++;
}
else
{
_first.PrevItem = newItem;
newItem.PrevItem = null;
newItem.NextItem = _first;
_first = newItem;
_count++;
}
}
public void AddLast(LoopGridViewItem newItem)
{
newItem.PrevItem = null;
newItem.NextItem = null;
if (_first == null)
{
_first = newItem;
_last = newItem;
_first.PrevItem = null;
_first.NextItem = null;
_count++;
}
else
{
_last.NextItem = newItem;
newItem.PrevItem = _last;
newItem.NextItem = null;
_last = newItem;
_count++;
}
}
public LoopGridViewItem RemoveFirst()
{
LoopGridViewItem ret = _first;
if (_first == null)
{
return ret;
}
if(_first == _last)
{
_first = null;
_last = null;
--_count;
return ret;
}
_first = _first.NextItem;
_first.PrevItem = null;
--_count;
return ret;
}
public LoopGridViewItem RemoveLast()
{
LoopGridViewItem ret = _last;
if (_first == null)
{
return ret;
}
if (_first == _last)
{
_first = null;
_last = null;
--_count;
return ret;
}
_last = _last.PrevItem;
_last.NextItem = null;
--_count;
return ret;
}
public void Clear()
{
LoopGridViewItem current = _first;
while (current != null)
{
current.PrevItem = null;
current.NextItem = null;
current = current.NextItem;
}
_first = null;
_last = null;
_count = 0;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f7e7eb25fe1319d4b8773ddfab7a240e
timeCreated: 1554538573
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace GameLogic
{
public class GridItemPool
{
private GameObject _prefabObj;
private string _prefabName;
private int _initCreateCount = 1;
private readonly List<LoopGridViewItem> _tmpPooledItemList = new List<LoopGridViewItem>();
private readonly List<LoopGridViewItem> _pooledItemList = new List<LoopGridViewItem>();
private static int _curItemIdCount = 0;
private RectTransform _itemParent = null;
public GridItemPool()
{
}
public void Init(GameObject prefabObj, int createCount, RectTransform parent)
{
_prefabObj = prefabObj;
_prefabName = _prefabObj.name;
_initCreateCount = createCount;
_itemParent = parent;
_prefabObj.SetActive(false);
for (int i = 0; i < _initCreateCount; ++i)
{
LoopGridViewItem tViewItem = CreateItem();
RecycleItemReal(tViewItem);
}
}
public LoopGridViewItem GetItem()
{
_curItemIdCount++;
LoopGridViewItem tItem = null;
if (_tmpPooledItemList.Count > 0)
{
int count = _tmpPooledItemList.Count;
tItem = _tmpPooledItemList[count - 1];
_tmpPooledItemList.RemoveAt(count - 1);
tItem.gameObject.SetActive(true);
}
else
{
int count = _pooledItemList.Count;
if (count == 0)
{
tItem = CreateItem();
}
else
{
tItem = _pooledItemList[count - 1];
_pooledItemList.RemoveAt(count - 1);
tItem.gameObject.SetActive(true);
}
}
tItem.ItemId = _curItemIdCount;
return tItem;
}
public void DestroyAllItem()
{
ClearTmpRecycledItem();
int count = _pooledItemList.Count;
for (int i = 0; i < count; ++i)
{
GameObject.DestroyImmediate(_pooledItemList[i].gameObject);
}
_pooledItemList.Clear();
}
public LoopGridViewItem CreateItem()
{
GameObject go = GameObject.Instantiate<GameObject>(_prefabObj, Vector3.zero, Quaternion.identity, _itemParent);
go.SetActive(true);
RectTransform rf = go.GetComponent<RectTransform>();
rf.localScale = Vector3.one;
rf.anchoredPosition3D = Vector3.zero;
rf.localEulerAngles = Vector3.zero;
LoopGridViewItem tViewItem = go.GetComponent<LoopGridViewItem>();
tViewItem.ItemPrefabName = _prefabName;
tViewItem.GoId = go.GetHashCode();
return tViewItem;
}
void RecycleItemReal(LoopGridViewItem item)
{
item.gameObject.SetActive(false);
_pooledItemList.Add(item);
}
public void RecycleItem(LoopGridViewItem item)
{
item.PrevItem = null;
item.NextItem = null;
_tmpPooledItemList.Add(item);
}
public void ClearTmpRecycledItem()
{
int count = _tmpPooledItemList.Count;
if (count == 0)
{
return;
}
for (int i = 0; i < count; ++i)
{
RecycleItemReal(_tmpPooledItemList[i]);
}
_tmpPooledItemList.Clear();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c1eb92a17e8cee642a2245950dfaabea
timeCreated: 1554538573
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 17e9881a7bce8124a8f855b96a8ca11a
timeCreated: 1554538573
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,184 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GameLogic
{
public class LoopGridViewItem : MonoBehaviour
{
// indicates the items index in the list the mItemIndex can only be from 0 to itemTotalCount -1.
int mItemIndex = -1;
// the row index, the item is in. starting from 0.
int mRow = -1;
// the column index, the item is in. starting from 0.
int mColumn = -1;
//indicates the items id.
//This property is set when the item is created or fetched from pool,
//and will no longer change until the item is recycled back to pool.
int mItemId = -1;
private int _goId = 0;
public int GoId
{
set => _goId = value;
get => _goId;
}
LoopGridView mParentGridView = null;
bool mIsInitHandlerCalled = false;
string mItemPrefabName;
RectTransform mCachedRectTransform;
int mItemCreatedCheckFrameCount = 0;
object mUserObjectData = null;
int mUserIntData1 = 0;
int mUserIntData2 = 0;
string mUserStringData1 = null;
string mUserStringData2 = null;
LoopGridViewItem mPrevItem;
LoopGridViewItem mNextItem;
public object UserObjectData
{
get { return mUserObjectData; }
set { mUserObjectData = value; }
}
public int UserIntData1
{
get { return mUserIntData1; }
set { mUserIntData1 = value; }
}
public int UserIntData2
{
get { return mUserIntData2; }
set { mUserIntData2 = value; }
}
public string UserStringData1
{
get { return mUserStringData1; }
set { mUserStringData1 = value; }
}
public string UserStringData2
{
get { return mUserStringData2; }
set { mUserStringData2 = value; }
}
public int ItemCreatedCheckFrameCount
{
get { return mItemCreatedCheckFrameCount; }
set { mItemCreatedCheckFrameCount = value; }
}
public RectTransform CachedRectTransform
{
get
{
if (mCachedRectTransform == null)
{
mCachedRectTransform = gameObject.GetComponent<RectTransform>();
}
return mCachedRectTransform;
}
}
public string ItemPrefabName
{
get
{
return mItemPrefabName;
}
set
{
mItemPrefabName = value;
}
}
public int Row
{
get
{
return mRow;
}
set
{
mRow = value;
}
}
public int Column
{
get
{
return mColumn;
}
set
{
mColumn = value;
}
}
public int ItemIndex
{
get
{
return mItemIndex;
}
set
{
mItemIndex = value;
}
}
public int ItemId
{
get
{
return mItemId;
}
set
{
mItemId = value;
}
}
public bool IsInitHandlerCalled
{
get
{
return mIsInitHandlerCalled;
}
set
{
mIsInitHandlerCalled = value;
}
}
public LoopGridView ParentGridView
{
get
{
return mParentGridView;
}
set
{
mParentGridView = value;
}
}
public LoopGridViewItem PrevItem
{
get { return mPrevItem; }
set { mPrevItem = value; }
}
public LoopGridViewItem NextItem
{
get { return mNextItem; }
set { mNextItem = value; }
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ec0432517adfcb84bb6163d7a44ab8c1
timeCreated: 1554538573
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e9bbd48a4abc45c46a92b92d0df3ae07
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -8,23 +8,6 @@ using Object = UnityEngine.Object;
namespace GameLogic
{
public enum ItemCornerEnum
{
LeftBottom = 0,
LeftTop,
RightTop,
RightBottom,
}
public enum ListItemArrangeType
{
TopToBottom,
BottomToTop,
LeftToRight,
RightToLeft,
}
public class ItemPool
{
private GameObject _prefabObj;
@@ -171,13 +154,6 @@ namespace GameLogic
public delegate LoopListViewItem
OnGetItemByIndex(LoopListView listView, int index); // System.Func<LoopListView, int, LoopListViewItem>
public enum SnapStatus
{
NoTargetSet = 0,
TargetHasSet = 1,
SnapMoving = 2,
SnapMoveFinish = 3
}
public class LoopListView : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler
{

View File

@@ -0,0 +1,14 @@
namespace GameLogic
{
public class UILoopGridItemWidget: SelectItemBase
{
public LoopGridViewItem LoopItem { set; get; }
public int Index { private set; get; }
public virtual void UpdateItem(int index)
{
Index = index;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 47ee457a0d7549b3a3b5d23f4ac048cd
timeCreated: 1692346002

View File

@@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace GameLogic
{
/// <summary>
/// UI列表。
/// </summary>
public class UILoopGridWidget<TItem, TData> : UIListBase<TItem, TData> where TItem : UILoopGridItemWidget, new()
{
/// <summary>
/// LoopRectView
/// </summary>
public LoopGridView LoopRectView { private set; get; }
/// <summary>
/// Item字典
/// </summary>
private Dictionary<int, TItem> m_itemCache = new Dictionary<int, TItem>();
/// <summary>
/// 计算偏差后的ItemList
/// </summary>
private List<TItem> m_items = new List<TItem>();
/// <summary>
/// 计算偏差后的ItemList
/// </summary>
public List<TItem> items => m_items;
public override void BindMemberProperty()
{
base.BindMemberProperty();
LoopRectView = rectTransform.GetComponent<LoopGridView>();
}
public override void OnCreate()
{
base.OnCreate();
LoopRectView.InitGridView(0, OnGetItemByIndex);
}
public override void OnDestroy()
{
base.OnDestroy();
m_itemCache.Clear();
}
/// <summary>
/// Item回调函数
/// </summary>
protected Action<TItem, int> m_tpFuncItem;
/// <summary>
/// 设置显示数据
/// </summary>
/// <param name="n"></param>
/// <param name="datas"></param>
/// <param name="funcItem"></param>
protected override void AdjustItemNum(int n, List<TData> datas = null, Action<TItem, int> funcItem = null)
{
base.AdjustItemNum(n, datas, funcItem);
m_tpFuncItem = funcItem;
LoopRectView.SetListItemCount(n);
LoopRectView.RefreshAllShownItem();
m_tpFuncItem = null;
}
/// <summary>
/// 获取Item
/// </summary>
/// <param name="listView"></param>
/// <param name="itemIndex"></param>
/// <param name="row"></param>
/// <param name="column"></param>
/// <returns></returns>
protected LoopGridViewItem OnGetItemByIndex(LoopGridView listView, int itemIndex,int row,int column)
{
if (itemIndex < 0 || itemIndex >= num) return null;
var item = itemBase == null ? CreateItem() : CreateItem(itemBase);
if (item == null) return null;
item.SetItemIndex(itemIndex);
UpdateListItem(item, itemIndex, m_tpFuncItem);
return item.LoopItem;
}
/// <summary>
/// 创建Item
/// </summary>
/// <returns></returns>
public TItem CreateItem()
{
return CreateItem(typeof(TItem).Name);
}
/// <summary>
/// 创建Item
/// </summary>
/// <param name="itemName"></param>
/// <returns></returns>
public TItem CreateItem(string itemName)
{
TItem widget = null;
LoopGridViewItem item = LoopRectView.AllocOrNewListViewItem(itemName);
if (item != null)
{
widget = CreateItem(item);
}
return widget;
}
/// <summary>
/// 创建Item
/// </summary>
/// <param name="prefab"></param>
/// <returns></returns>
public TItem CreateItem(GameObject prefab)
{
TItem widget = null;
LoopGridViewItem item = LoopRectView.AllocOrNewListViewItem(prefab);
if (item != null)
{
widget = CreateItem(item);
}
return widget;
}
/// <summary>
/// 创建Item
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private TItem CreateItem(LoopGridViewItem item)
{
TItem widget;
if (!m_itemCache.TryGetValue(item.GoId, out widget))
{
widget = CreateWidget<TItem>(item.gameObject);
widget.LoopItem = item;
m_itemCache.Add(item.GoId, widget);
}
return widget;
}
/// <summary>
/// 获取item
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public override TItem GetItem(int i)
{
return i >= 0 && i < m_items.Count ? m_items[i] : null;
}
/// <summary>
/// 获取itemList
/// </summary>
/// <returns></returns>
public List<TItem> GetItemList()
{
m_items.Clear();
for (int i = 0; i < m_itemCache.Count; i++)
{
m_items.Add(m_itemCache[i]);
}
return m_items;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0930448d067145dfb0428b248f1086ae
timeCreated: 1692346037

View File

@@ -7,7 +7,7 @@ namespace GameLogic
/// <summary>
/// UI列表。
/// </summary>
public class UILoopListWidget<ItemT, DataT> : UIListBase<ItemT, DataT> where ItemT : UILoopItemWidget, new()
public class UILoopListWidget<TItem, TData> : UIListBase<TItem, TData> where TItem : UILoopItemWidget, new()
{
/// <summary>
/// LoopRectView
@@ -17,17 +17,17 @@ namespace GameLogic
/// <summary>
/// Item字典
/// </summary>
private Dictionary<int, ItemT> m_itemCache = new Dictionary<int, ItemT>();
private Dictionary<int, TItem> m_itemCache = new Dictionary<int, TItem>();
/// <summary>
/// 计算偏差后的ItemList
/// </summary>
private List<ItemT> m_items = new List<ItemT>();
private List<TItem> m_items = new List<TItem>();
/// <summary>
/// 计算偏差后的ItemList
/// </summary>
public List<ItemT> items => m_items;
public List<TItem> items => m_items;
public override void BindMemberProperty()
{
@@ -50,7 +50,7 @@ namespace GameLogic
/// <summary>
/// Item回调函数
/// </summary>
protected Action<ItemT, int> m_tpFuncItem;
protected Action<TItem, int> m_tpFuncItem;
/// <summary>
/// 设置显示数据
@@ -58,7 +58,7 @@ namespace GameLogic
/// <param name="n"></param>
/// <param name="datas"></param>
/// <param name="funcItem"></param>
protected override void AdjustItemNum(int n, List<DataT> datas = null, Action<ItemT, int> funcItem = null)
protected override void AdjustItemNum(int n, List<TData> datas = null, Action<TItem, int> funcItem = null)
{
base.AdjustItemNum(n, datas, funcItem);
m_tpFuncItem = funcItem;
@@ -87,9 +87,9 @@ namespace GameLogic
/// 创建Item
/// </summary>
/// <returns></returns>
public ItemT CreateItem()
public TItem CreateItem()
{
return CreateItem(typeof(ItemT).Name);
return CreateItem(typeof(TItem).Name);
}
/// <summary>
@@ -97,9 +97,9 @@ namespace GameLogic
/// </summary>
/// <param name="itemName"></param>
/// <returns></returns>
public ItemT CreateItem(string itemName)
public TItem CreateItem(string itemName)
{
ItemT widget = null;
TItem widget = null;
LoopListViewItem item = LoopRectView.AllocOrNewListViewItem(itemName);
if (item != null)
{
@@ -113,9 +113,9 @@ namespace GameLogic
/// </summary>
/// <param name="prefab"></param>
/// <returns></returns>
public ItemT CreateItem(GameObject prefab)
public TItem CreateItem(GameObject prefab)
{
ItemT widget = null;
TItem widget = null;
LoopListViewItem item = LoopRectView.AllocOrNewListViewItem(prefab);
if (item != null)
{
@@ -129,12 +129,12 @@ namespace GameLogic
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private ItemT CreateItem(LoopListViewItem item)
private TItem CreateItem(LoopListViewItem item)
{
ItemT widget;
TItem widget;
if (!m_itemCache.TryGetValue(item.GoId, out widget))
{
widget = CreateWidget<ItemT>(item.gameObject);
widget = CreateWidget<TItem>(item.gameObject);
widget.LoopItem = item;
m_itemCache.Add(item.GoId, widget);
}
@@ -147,7 +147,7 @@ namespace GameLogic
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public override ItemT GetItem(int i)
public override TItem GetItem(int i)
{
return i >= 0 && i < m_items.Count ? m_items[i] : null;
}
@@ -156,7 +156,7 @@ namespace GameLogic
/// 获取itemList
/// </summary>
/// <returns></returns>
public List<ItemT> GetItemList()
public List<TItem> GetItemList()
{
m_items.Clear();
for (int i = 0; i < m_itemCache.Count; i++)