[+] UI循环列表拓展与示例

[+] UI循环列表拓展与示例
This commit is contained in:
ALEXTANG
2023-08-10 23:25:43 +08:00
parent ea9447d0ea
commit 53f0ecb6c1
22 changed files with 4700 additions and 558 deletions

View File

@@ -1,16 +1,28 @@
using System.Collections.Generic;
using GameLogic;
using UnityEngine;
using UnityEngine.UI;
using TEngine;
class TempData
{
}
class TempItem : UILoopItemWidget, IListDataItem<TempData>
{
public void SetItemData(TempData d)
{
}
}
[Window(UILayer.UI)]
class NetWorkDemoUI : UIWindow
{
protected UILoopListWidget<TempItem, TempData> m_loopList;
#region
private GameObject m_goScrollView;
private Transform m_tfContent;
private GameObject m_itemNetLog;
private GameObject m_goConnect;
private Button m_btnConnect;
private GameObject m_goLogin;
@@ -18,12 +30,11 @@ class NetWorkDemoUI : UIWindow
private InputField m_inputName;
private Button m_btnLogin;
private Button m_btnRegister;
private ScrollRect m_scrollRect;
private Transform m_tfContent;
private GameObject m_itemTemp;
public override void ScriptGenerator()
{
m_goScrollView = FindChild("Panel/m_goScrollView").gameObject;
m_tfContent = FindChild("Panel/m_goScrollView/Viewport/m_tfContent");
m_itemNetLog = FindChild("Panel/m_goScrollView/Viewport/m_tfContent/m_itemNetLog").gameObject;
m_goConnect = FindChild("Panel/m_goConnect").gameObject;
m_btnConnect = FindChildComponent<Button>("Panel/m_goConnect/m_btnConnect");
m_goLogin = FindChild("Panel/m_goLogin").gameObject;
@@ -31,13 +42,28 @@ class NetWorkDemoUI : UIWindow
m_inputName = FindChildComponent<InputField>("Panel/m_goLogin/m_inputName");
m_btnLogin = FindChildComponent<Button>("Panel/m_goLogin/m_btnLogin");
m_btnRegister = FindChildComponent<Button>("Panel/m_goLogin/m_btnRegister");
m_scrollRect = FindChildComponent<ScrollRect>("Panel/m_scrollRect");
m_tfContent = FindChild("Panel/m_scrollRect/Viewport/m_tfContent");
m_itemTemp = FindChild("Panel/m_scrollRect/Viewport/m_tfContent/m_itemTemp").gameObject;
m_btnConnect.onClick.AddListener(OnClickConnectBtn);
m_btnLogin.onClick.AddListener(OnClickLoginBtn);
m_btnRegister.onClick.AddListener(OnClickRegisterBtn);
}
#endregion
public override void OnRefresh()
{
m_loopList = CreateWidget<UILoopListWidget<TempItem, TempData>>(m_scrollRect.gameObject);
m_loopList.itemBase = m_itemTemp;
List<TempData> datas = new List<TempData>();
for (int i = 0; i < 100; i++)
{
datas.Add(new TempData());
}
m_loopList.SetDatas(datas);
base.OnRefresh();
}
#region
private void OnClickConnectBtn()

View File

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

View File

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

View File

@@ -0,0 +1,84 @@
using UnityEngine;
using UnityEngine.EventSystems;
namespace GameLogic
{
public class ClickEventListener : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler
{
public static ClickEventListener Get(GameObject obj)
{
ClickEventListener listener = obj.GetComponent<ClickEventListener>();
if (listener == null)
{
listener = obj.AddComponent<ClickEventListener>();
}
return listener;
}
private System.Action<GameObject> _clickedHandler = null;
private System.Action<GameObject> _doubleClickedHandler = null;
private System.Action<GameObject> _onPointerDownHandler = null;
private System.Action<GameObject> _onPointerUpHandler = null;
bool _isPressed = false;
public bool IsPressed => _isPressed;
public void OnPointerClick(PointerEventData eventData)
{
if (eventData.clickCount == 2)
{
if (_doubleClickedHandler != null)
{
_doubleClickedHandler(gameObject);
}
}
else
{
if (_clickedHandler != null)
{
_clickedHandler(gameObject);
}
}
}
public void SetClickEventHandler(System.Action<GameObject> handler)
{
_clickedHandler = handler;
}
public void SetDoubleClickEventHandler(System.Action<GameObject> handler)
{
_doubleClickedHandler = handler;
}
public void SetPointerDownHandler(System.Action<GameObject> handler)
{
_onPointerDownHandler = handler;
}
public void SetPointerUpHandler(System.Action<GameObject> handler)
{
_onPointerUpHandler = handler;
}
public void OnPointerDown(PointerEventData eventData)
{
_isPressed = true;
if (_onPointerDownHandler != null)
{
_onPointerDownHandler(gameObject);
}
}
public void OnPointerUp(PointerEventData eventData)
{
_isPressed = false;
if (_onPointerUpHandler != null)
{
_onPointerUpHandler(gameObject);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aa13a2165836fda459a6c28562ac101a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,326 @@
using System;
using System.Collections.Generic;
namespace GameLogic
{
public class ItemSizeGroup
{
public float[] ItemSizeArray = null;
public float[] ItemStartPosArray = null;
public int ItemCount = 0;
private int _dirtyBeginIndex = ItemPosMgr.ItemMaxCountPerGroup;
public float GroupSize = 0;
public float GroupStartPos = 0;
public float GroupEndPos = 0;
public int GroupIndex = 0;
public float ItemDefaultSize = 0;
public ItemSizeGroup(int index, float itemDefaultSize)
{
GroupIndex = index;
ItemDefaultSize = itemDefaultSize;
Init();
}
public void Init()
{
ItemSizeArray = new float[ItemPosMgr.ItemMaxCountPerGroup];
if (ItemDefaultSize != 0)
{
for (int i = 0; i < ItemSizeArray.Length; ++i)
{
ItemSizeArray[i] = ItemDefaultSize;
}
}
ItemStartPosArray = new float[ItemPosMgr.ItemMaxCountPerGroup];
ItemStartPosArray[0] = 0;
ItemCount = ItemPosMgr.ItemMaxCountPerGroup;
GroupSize = ItemDefaultSize * ItemSizeArray.Length;
if (ItemDefaultSize != 0)
{
_dirtyBeginIndex = 0;
}
else
{
_dirtyBeginIndex = ItemPosMgr.ItemMaxCountPerGroup;
}
}
public float GetItemStartPos(int index)
{
return GroupStartPos + ItemStartPosArray[index];
}
public bool IsDirty
{
get { return (_dirtyBeginIndex < ItemCount); }
}
public float SetItemSize(int index, float size)
{
float old = ItemSizeArray[index];
if (Math.Abs(old - size) < 0.001f)
{
return 0;
}
ItemSizeArray[index] = size;
if (index < _dirtyBeginIndex)
{
_dirtyBeginIndex = index;
}
float ds = size - old;
GroupSize = GroupSize + ds;
return ds;
}
public void SetItemCount(int count)
{
if (ItemCount == count)
{
return;
}
ItemCount = count;
RecalcGroupSize();
}
public void RecalcGroupSize()
{
GroupSize = 0;
for (int i = 0; i < ItemCount; ++i)
{
GroupSize += ItemSizeArray[i];
}
}
public int GetItemIndexByPos(float pos)
{
if (ItemCount == 0)
{
return -1;
}
int low = 0;
int high = ItemCount - 1;
while (low <= high)
{
int mid = (low + high) / 2;
float startPos = ItemStartPosArray[mid];
float endPos = startPos + ItemSizeArray[mid];
if (startPos <= pos && endPos >= pos)
{
return mid;
}
else if (pos > endPos)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
return -1;
}
public void UpdateAllItemStartPos()
{
if (_dirtyBeginIndex >= ItemCount)
{
return;
}
int startIndex = (_dirtyBeginIndex < 1) ? 1 : _dirtyBeginIndex;
for (int i = startIndex; i < ItemCount; ++i)
{
ItemStartPosArray[i] = ItemStartPosArray[i - 1] + ItemSizeArray[i - 1];
}
_dirtyBeginIndex = ItemCount;
}
}
public class ItemPosMgr
{
public const int ItemMaxCountPerGroup = 100;
readonly List<ItemSizeGroup> _itemSizeGroupList = new List<ItemSizeGroup>();
public int _dirtyBeginIndex = int.MaxValue;
public float TotalSize = 0;
public float ItemDefaultSize = 20;
public ItemPosMgr(float itemDefaultSize)
{
ItemDefaultSize = itemDefaultSize;
}
public void SetItemMaxCount(int maxCount)
{
_dirtyBeginIndex = 0;
TotalSize = 0;
int st = maxCount % ItemMaxCountPerGroup;
int lastGroupItemCount = st;
int needMaxGroupCount = maxCount / ItemMaxCountPerGroup;
if (st > 0)
{
needMaxGroupCount++;
}
else
{
lastGroupItemCount = ItemMaxCountPerGroup;
}
int count = _itemSizeGroupList.Count;
if (count > needMaxGroupCount)
{
int d = count - needMaxGroupCount;
_itemSizeGroupList.RemoveRange(needMaxGroupCount, d);
}
else if (count < needMaxGroupCount)
{
int d = needMaxGroupCount - count;
for (int i = 0; i < d; ++i)
{
ItemSizeGroup tGroup = new ItemSizeGroup(count + i, ItemDefaultSize);
_itemSizeGroupList.Add(tGroup);
}
}
count = _itemSizeGroupList.Count;
if (count == 0)
{
return;
}
for (int i = 0; i < count - 1; ++i)
{
_itemSizeGroupList[i].SetItemCount(ItemMaxCountPerGroup);
}
_itemSizeGroupList[count - 1].SetItemCount(lastGroupItemCount);
for (int i = 0; i < count; ++i)
{
TotalSize = TotalSize + _itemSizeGroupList[i].GroupSize;
}
}
public void SetItemSize(int itemIndex, float size)
{
int groupIndex = itemIndex / ItemMaxCountPerGroup;
int indexInGroup = itemIndex % ItemMaxCountPerGroup;
ItemSizeGroup tGroup = _itemSizeGroupList[groupIndex];
float changedSize = tGroup.SetItemSize(indexInGroup, size);
if (changedSize != 0f)
{
if (groupIndex < _dirtyBeginIndex)
{
_dirtyBeginIndex = groupIndex;
}
}
TotalSize += changedSize;
}
public float GetItemPos(int itemIndex)
{
Update(true);
int groupIndex = itemIndex / ItemMaxCountPerGroup;
int indexInGroup = itemIndex % ItemMaxCountPerGroup;
return _itemSizeGroupList[groupIndex].GetItemStartPos(indexInGroup);
}
public void GetItemIndexAndPosAtGivenPos(float pos, ref int index, ref float itemPos)
{
Update(true);
index = 0;
itemPos = 0f;
int count = _itemSizeGroupList.Count;
if (count == 0)
{
return;
}
ItemSizeGroup hitGroup = null;
int low = 0;
int high = count - 1;
while (low <= high)
{
int mid = (low + high) / 2;
ItemSizeGroup tGroup = _itemSizeGroupList[mid];
if (tGroup.GroupStartPos <= pos && tGroup.GroupEndPos >= pos)
{
hitGroup = tGroup;
break;
}
else if (pos > tGroup.GroupEndPos)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
int hitIndex = -1;
if (hitGroup != null)
{
hitIndex = hitGroup.GetItemIndexByPos(pos - hitGroup.GroupStartPos);
}
else
{
return;
}
if (hitIndex < 0)
{
return;
}
index = hitIndex + hitGroup.GroupIndex * ItemMaxCountPerGroup;
itemPos = hitGroup.GetItemStartPos(hitIndex);
}
public void Update(bool updateAll)
{
int count = _itemSizeGroupList.Count;
if (count == 0)
{
return;
}
if (_dirtyBeginIndex >= count)
{
return;
}
int loopCount = 0;
for (int i = _dirtyBeginIndex; i < count; ++i)
{
loopCount++;
ItemSizeGroup tGroup = _itemSizeGroupList[i];
_dirtyBeginIndex++;
tGroup.UpdateAllItemStartPos();
if (i == 0)
{
tGroup.GroupStartPos = 0;
tGroup.GroupEndPos = tGroup.GroupSize;
}
else
{
tGroup.GroupStartPos = _itemSizeGroupList[i - 1].GroupEndPos;
tGroup.GroupEndPos = tGroup.GroupStartPos + tGroup.GroupSize;
}
if (!updateAll && loopCount > 1)
{
return;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61adb6a884bfbfc4292a5d39261a74f2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dd536d252034dd74b87b436507ec44f7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,216 @@
using UnityEngine;
namespace GameLogic
{
public class LoopListViewItem : MonoBehaviour
{
public float Padding;
private int _itemIndex = -1;
private int _itemId = -1;
private LoopListView _parentListView = null;
private bool _isInitHandlerCalled = false;
private string _itemPrefabName;
private RectTransform _cachedRectTransform;
private float _padding;
private float _distanceWithViewPortSnapCenter = 0;
private int _itemCreatedCheckFrameCount = 0;
private float _startPosOffset = 0;
private object _userObjectData = null;
private int _userIntData1 = 0;
private int _userIntData2 = 0;
private string _userStringData1 = null;
private string _userStringData2 = null;
private int _goId = 0;
public int GoId
{
set => _goId = value;
get => _goId;
}
public object UserObjectData
{
get => _userObjectData;
set => _userObjectData = value;
}
public int UserIntData1
{
get => _userIntData1;
set => _userIntData1 = value;
}
public int UserIntData2
{
get => _userIntData2;
set => _userIntData2 = value;
}
public string UserStringData1
{
get => _userStringData1;
set => _userStringData1 = value;
}
public string UserStringData2
{
get => _userStringData2;
set => _userStringData2 = value;
}
public float DistanceWithViewPortSnapCenter
{
get => _distanceWithViewPortSnapCenter;
set => _distanceWithViewPortSnapCenter = value;
}
public float StartPosOffset
{
get => _startPosOffset;
set => _startPosOffset = value;
}
public int ItemCreatedCheckFrameCount
{
get => _itemCreatedCheckFrameCount;
set => _itemCreatedCheckFrameCount = value;
}
public RectTransform CachedRectTransform
{
get
{
if (_cachedRectTransform == null)
{
_cachedRectTransform = gameObject.GetComponent<RectTransform>();
}
return _cachedRectTransform;
}
}
public string ItemPrefabName
{
get => _itemPrefabName;
set => _itemPrefabName = value;
}
public int ItemIndex
{
get => _itemIndex;
set => _itemIndex = value;
}
public int ItemId
{
get => _itemId;
set => _itemId = value;
}
public bool IsInitHandlerCalled
{
get => _isInitHandlerCalled;
set => _isInitHandlerCalled = value;
}
public LoopListView ParentListView
{
get => _parentListView;
set => _parentListView = value;
}
public float TopY
{
get
{
ListItemArrangeType arrageType = ParentListView.ArrangeType;
if (arrageType == ListItemArrangeType.TopToBottom)
{
return CachedRectTransform.localPosition.y;
}
else if (arrageType == ListItemArrangeType.BottomToTop)
{
return CachedRectTransform.localPosition.y + CachedRectTransform.rect.height;
}
return 0;
}
}
public float BottomY
{
get
{
ListItemArrangeType arrageType = ParentListView.ArrangeType;
if (arrageType == ListItemArrangeType.TopToBottom)
{
return CachedRectTransform.localPosition.y - CachedRectTransform.rect.height;
}
else if (arrageType == ListItemArrangeType.BottomToTop)
{
return CachedRectTransform.localPosition.y;
}
return 0;
}
}
public float LeftX
{
get
{
ListItemArrangeType arrageType = ParentListView.ArrangeType;
if (arrageType == ListItemArrangeType.LeftToRight)
{
return CachedRectTransform.localPosition.x;
}
else if (arrageType == ListItemArrangeType.RightToLeft)
{
return CachedRectTransform.localPosition.x - CachedRectTransform.rect.width;
}
return 0;
}
}
public float RightX
{
get
{
ListItemArrangeType arrageType = ParentListView.ArrangeType;
if (arrageType == ListItemArrangeType.LeftToRight)
{
return CachedRectTransform.localPosition.x + CachedRectTransform.rect.width;
}
else if (arrageType == ListItemArrangeType.RightToLeft)
{
return CachedRectTransform.localPosition.x;
}
return 0;
}
}
public float ItemSize
{
get
{
if (ParentListView.IsVertList)
{
return CachedRectTransform.rect.height;
}
else
{
return CachedRectTransform.rect.width;
}
}
}
public float ItemSizeWithPadding => ItemSize + _padding;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29af6e9bda3402e4eba67bb72531e618
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -5,7 +5,7 @@ using UnityEngine.UI;
namespace GameLogic
{
class UIEventItem<T> : UIWidget where T : UIEventItem<T>
public class UIEventItem<T> : UIWidget where T : UIEventItem<T>
{
private object _eventParam1;
private object _eventParam2;

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a9c3cf3e98f544a7a1dd6cb8ac023d30
timeCreated: 1691679403

View File

@@ -0,0 +1,337 @@
using System;
using System.Collections.Generic;
using TEngine;
using UnityEngine;
using UnityEngine.UI;
namespace GameLogic
{
/// <summary>
/// UI列表Item
/// </summary>
/// <typeparam name="DataT"></typeparam>
public interface IListDataItem<in DataT>
{
void SetItemData(DataT d);
}
/// <summary>
/// UI列表Item
/// </summary>
public interface IListSelectItem
{
/// <summary>
/// 获取索引。
/// </summary>
/// <returns></returns>
int GetItemIndex();
/// <summary>
/// 设置索引。
/// </summary>
/// <param name="i"></param>
void SetItemIndex(int i);
/// <summary>
/// 是否被选中。
/// </summary>
/// <returns></returns>
bool IsSelected();
/// <summary>
/// 设置是否选中。
/// </summary>
/// <param name="v"></param>
void SetSelected(bool v);
}
public class SelectItemBase : UIEventItem<SelectItemBase>, IListSelectItem
{
/// <summary>
/// 索引。
/// </summary>
protected int m_itemIndex;
public int GetItemIndex()
{
return m_itemIndex;
}
public void SetItemIndex(int i)
{
m_itemIndex = i;
}
/// <summary>
/// 是否被选中。
/// </summary>
protected bool m_isSelected;
public virtual bool IsSelected()
{
return m_isSelected;
}
public virtual void SetSelected(bool v)
{
if (m_isSelected == v) return;
m_isSelected = v;
UpdateSelect();
}
/// <summary>
/// 刷新选中状态。
/// </summary>
public virtual void UpdateSelect()
{
}
public override void RegisterEvent()
{
base.RegisterEvent();
AddSelectEvt();
}
/// <summary>
/// 监听选中事件。
/// </summary>
protected virtual void AddSelectEvt()
{
if (Parent == null || !(Parent is IUISelectList)) return;
var btn = TEngine.DUnityUtil.AddMonoBehaviour<Button>(gameObject);
if (btn != null)
{
btn.onClick.AddListener(OnSelectClick);
}
}
/// <summary>
/// 选中点击
/// </summary>
protected virtual void OnSelectClick()
{
var p = Parent as IUISelectList;
if (p != null)
{
p.OnItemClick(this, GetItemIndex());
}
}
}
interface IUISelectList
{
void OnItemClick(object item, int i);
}
/// <summary>
/// UI列表
/// </summary>
public class UIListBase<ItemT, DataT> : UIWidget, IUISelectList where ItemT : UIWidget, new()
{
/// <summary>
/// item模板
/// </summary>
public GameObject itemBase;
/// <summary>
/// 数据列表
/// </summary>
protected List<DataT> m_datas;
/// <summary>
/// 数据列表
/// </summary>
public List<DataT> datas => m_datas;
/// <summary>
/// 数据数量
/// </summary>
public int DataNum => m_datas?.Count ?? 0;
/// <summary>
/// 数量
/// </summary>
protected int m_num;
/// <summary>
/// 数量
/// </summary>
public int num => m_num;
/// <summary>
/// 设置数据数量
/// </summary>
/// <param name="n"></param>
/// <param name="funcItem"></param>
public void SetDataNum(int n, Action<ItemT, int> funcItem = null)
{
AdjustItemNum(n, null, funcItem);
}
/// <summary>
/// 数据起始索引
/// </summary>
public int dataStartOffset = 0;
/// <summary>
/// 设置数据
/// </summary>
/// <param name="dataList"></param>
/// <param name="n"></param>
public void SetDatas(List<DataT> dataList, int n = -1)
{
AdjustItemNum(Mathf.Max(0, n >= 0 ? n : (dataList == null ? 0 : (dataList.Count - dataStartOffset))),
dataList);
}
/// <summary>
/// 设置显示数据
/// </summary>
/// <param name="n"></param>
/// <param name="datas"></param>
/// <param name="funcItem"></param>
protected virtual void AdjustItemNum(int n, List<DataT> datas = null, Action<ItemT, int> funcItem = null)
{
m_num = n;
m_datas = datas;
if (itemBase != null)
{
itemBase.SetActive(false);
}
}
/// <summary>
/// 刷新列表ITEM
/// </summary>
/// <param name="item"></param>
/// <param name="i"></param>
/// <param name="func"></param>
protected virtual void UpdateListItem(ItemT item, int i, Action<ItemT, int> func)
{
if (item == null) return;
if (func != null)
{
func.Invoke(item, i);
return;
}
var listDataItem = item as IListDataItem<DataT>;
if (listDataItem != null)
{
listDataItem.SetItemData(GetData(i));
}
}
/// <summary>
/// 选中索引
/// </summary>
protected int m_selectIndex = -1;
/// <summary>
/// Item点击
/// </summary>
public Action<int> funcOnItemClick;
/// <summary>
/// 选中变化回调函数
/// </summary>
public Action funcOnSelectChange;
/// <summary>
/// 点击无选中变化回调
/// </summary>
public Action funcNoSelectChange;
/// <summary>
/// 选中索引
/// </summary>
public int selectIndex
{
get => m_selectIndex;
set => SetSelectIndex(value);
}
/// <summary>
/// 设置选中索引
/// </summary>
/// <param name="i"></param>
/// <param name="forceUpdate"></param>
/// <param name="triggerEvt"></param>
public void SetSelectIndex(int i, bool forceUpdate = false, bool triggerEvt = true)
{
if (!forceUpdate && m_selectIndex == i)
{
if (funcNoSelectChange != null)
{
funcNoSelectChange.Invoke();
}
return;
}
var preIndex = selectIndex;
m_selectIndex = i;
var item = GetItem(preIndex) as IListSelectItem;
if (item != null)
{
item.SetSelected(false);
}
item = GetItem(selectIndex) as IListSelectItem;
if (item != null)
{
item.SetSelected(true);
}
if (triggerEvt && funcOnSelectChange != null)
{
funcOnSelectChange.Invoke();
}
}
/// <summary>
/// 获取当前选中的数据
/// </summary>
/// <returns></returns>
public DataT GetSelectData()
{
return GetData(selectIndex);
}
/// <summary>
/// 获取数据
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public DataT GetData(int i)
{
i += dataStartOffset;
return m_datas == null || i < 0 || i >= m_datas.Count ? default(DataT) : m_datas[i];
}
/// <summary>
/// 获取item
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public virtual ItemT GetItem(int i)
{
return null;
}
/// <summary>
/// item被点击
/// </summary>
/// <param name="item"></param>
/// <param name="i"></param>
public void OnItemClick(object item, int i)
{
if (funcOnItemClick != null)
{
funcOnItemClick.Invoke(i);
}
selectIndex = i;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9d3742a744bb4934a4848b54bb6910a2
timeCreated: 1691679426

View File

@@ -0,0 +1,14 @@
namespace GameLogic
{
public class UILoopItemWidget : SelectItemBase
{
public LoopListViewItem 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: b39b2f052eec4a4a97256e5aeee9e7dc
timeCreated: 1691679577

View File

@@ -0,0 +1,95 @@
using System.Collections.Generic;
using TEngine;
using UnityEngine;
namespace GameLogic
{
public class UILoopListViewWidget<T> : UIWidget where T : UILoopItemWidget, new()
{
public LoopListView LoopRectView { private set; get; }
private Dictionary<int, T> m_itemCache = new Dictionary<int, T>();
public override void BindMemberProperty()
{
base.BindMemberProperty();
LoopRectView = this.rectTransform.GetComponent<LoopListView>();
}
public override void OnDestroy()
{
base.OnDestroy();
m_itemCache.Clear();
}
public T CreateItem()
{
string typeName = typeof(T).Name;
return CreateItem(typeName);
;
}
public T CreateItem(string itemName)
{
T widget = null;
var item = LoopRectView.AllocOrNewListViewItem(itemName);
if (item != null)
{
widget = CreateItem(item);
}
return widget;
}
public T CreateItem(GameObject prefab)
{
T widget = null;
var item = LoopRectView.AllocOrNewListViewItem(prefab);
if (item != null)
{
widget = CreateItem(item);
}
return widget;
}
private T CreateItem(LoopListViewItem item)
{
T widget;
if (!m_itemCache.TryGetValue(item.GoId, out widget))
{
widget = CreateWidget<T>(item.gameObject);
widget.LoopItem = item;
m_itemCache.Add(item.GoId, widget);
}
return widget;
}
public List<T> GetItemList()
{
List<T> list = new List<T>();
for (int i = 0; i < m_itemCache.Count; i++)
{
list.Add(m_itemCache[i]);
}
return list;
}
public int GetItemCount()
{
return m_itemCache.Count;
}
/// <summary>
/// 获取Item。
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public T GetItemByIndex(int index)
{
return m_itemCache[index];
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9b87126ba47740708bc82eb0bb9e414e
timeCreated: 1691679617

View File

@@ -0,0 +1,178 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace GameLogic
{
/// <summary>
/// UI列表。
/// </summary>
public class UILoopListWidget<ItemT, DataT> : UIListBase<ItemT, DataT> where ItemT : UILoopItemWidget, new()
{
/// <summary>
/// LoopRectView
/// </summary>
public LoopListView LoopRectView { private set; get; }
/// <summary>
/// Item字典
/// </summary>
private Dictionary<int, ItemT> m_itemCache = new Dictionary<int, ItemT>();
/// <summary>
/// 计算偏差后的ItemList
/// </summary>
private List<ItemT> m_items = new List<ItemT>();
/// <summary>
/// 计算偏差后的ItemList
/// </summary>
public List<ItemT> items => m_items;
public override void BindMemberProperty()
{
base.BindMemberProperty();
LoopRectView = rectTransform.GetComponent<LoopListView>();
}
public override void OnCreate()
{
base.OnCreate();
LoopRectView.InitListView(0, OnGetItemByIndex);
}
public override void OnDestroy()
{
base.OnDestroy();
m_itemCache.Clear();
}
/// <summary>
/// Item回调函数
/// </summary>
protected Action<ItemT, int> m_tpFuncItem;
/// <summary>
/// 设置显示数据
/// </summary>
/// <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)
{
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="index"></param>
/// <returns></returns>
protected LoopListViewItem OnGetItemByIndex(LoopListView listView, int index)
{
if (index < 0 || index >= num) return null;
var item = itemBase == null ? CreateItem() : CreateItem(itemBase);
if (item == null) return null;
item.SetItemIndex(index);
UpdateListItem(item, index, m_tpFuncItem);
return item.LoopItem;
}
/// <summary>
/// 创建Item
/// </summary>
/// <returns></returns>
public ItemT CreateItem()
{
return CreateItem(typeof(ItemT).Name);
}
/// <summary>
/// 创建Item
/// </summary>
/// <param name="itemName"></param>
/// <returns></returns>
public ItemT CreateItem(string itemName)
{
ItemT widget = null;
LoopListViewItem item = LoopRectView.AllocOrNewListViewItem(itemName);
if (item != null)
{
widget = CreateItem(item);
}
return widget;
}
/// <summary>
/// 创建Item
/// </summary>
/// <param name="prefab"></param>
/// <returns></returns>
public ItemT CreateItem(GameObject prefab)
{
ItemT widget = null;
LoopListViewItem item = LoopRectView.AllocOrNewListViewItem(prefab);
if (item != null)
{
widget = CreateItem(item);
}
return widget;
}
/// <summary>
/// 创建Item
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private ItemT CreateItem(LoopListViewItem item)
{
ItemT widget;
if (!m_itemCache.TryGetValue(item.GoId, out widget))
{
widget = CreateWidget<ItemT>(item.gameObject);
widget.LoopItem = item;
m_itemCache.Add(item.GoId, widget);
}
return widget;
}
/// <summary>
/// 获取item
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
public override ItemT GetItem(int i)
{
return i >= 0 && i < m_items.Count ? m_items[i] : null;
}
/// <summary>
/// 获取itemList
/// </summary>
/// <returns></returns>
public List<ItemT> GetItemList()
{
m_items.Clear();
for (int i = 0; i < m_itemCache.Count; i++)
{
m_items.Add(m_itemCache[i]);
}
return m_items;
}
/// <summary>
/// 获取当前起始索引
/// </summary>
/// <returns></returns>
public int GetItemStartIndex()
{
return LoopRectView.GetItemStartIndex();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 72b7444fb04642039aacc2db27dd002a
timeCreated: 1691679907