完成翻页管理器

This commit is contained in:
2025-07-25 19:20:51 +08:00
parent 3a4027561a
commit d4716ba5f8
2 changed files with 400 additions and 87 deletions
+163 -55
View File
@@ -1,8 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using Deconstruction.Runtime.UI;
using JetBrains.Annotations; using JetBrains.Annotations;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using XericLibrary.Runtime.MacroLibrary; using XericLibrary.Runtime.MacroLibrary;
@@ -120,7 +122,19 @@ namespace XericUI.FlipPage
#region 字段属性 #region 字段属性
protected ToggleGroup ToggleGroup;
private ToggleGroup _toggleGroup;
protected ToggleGroup ToggleGroup
{
get
{
if (_toggleGroup != null)
return _toggleGroup;
_toggleGroup = transform.GetComponentAnyway<ToggleGroup>();
return _toggleGroup;
}
}
#endregion #endregion
@@ -138,7 +152,7 @@ namespace XericUI.FlipPage
[LabelText("页面翻页按钮")] [LabelText("页面翻页按钮")]
#endif #endif
[CanBeNull] [CanBeNull]
internal ObjectVessel<Selectable, TMPro.TMP_Text> pageIndexSelectable; internal ObjectVessel<Selectable, TMPro.TMP_Text> pageSelectableVessel;
protected internal override void OnPageVisible(bool quickVisit) protected internal override void OnPageVisible(bool quickVisit)
{ {
@@ -146,18 +160,20 @@ namespace XericUI.FlipPage
return; return;
// 自动补全外部交互动画 // 自动补全外部交互动画
if (pageIndexSelectable.IsValidVessel() && if (pageSelectableVessel.IsValidVessel())
pageIndexSelectable.Target0 is Toggle toggle && SwitchSelectableVesselType(pageSelectableVessel.Target0,
!toggle.isOn) null,
{ toggle =>
toggle.SetIsOnWithoutNotify(true); {
if (!toggle.isOn)
} toggle.SetIsOnWithoutNotify(true);
});
} }
protected internal override void OnPageInvisible(bool quickVisit) protected internal override void OnPageInvisible(bool quickVisit)
{ {
} }
} }
/// <summary> /// <summary>
@@ -202,86 +218,128 @@ namespace XericUI.FlipPage
pageButtonPool.Init(); pageButtonPool.Init();
// 根据组件类型创建相关内容 // 根据组件类型创建相关内容
var prefabSelectable = pageButtonPool.Prefab.GetComponent<Selectable>(); // var prefabSelectable = pageButtonPool.Prefab.GetComponent<Selectable>();
switch (prefabSelectable)
{
// 单选项就创建但选项组
case Toggle toggle:
ToggleGroup = transform.GetComponentAnyway<ToggleGroup>();
break;
case Button button:
break;
default:
break;
}
} }
#endregion
#region 翻页功能
protected override void OnFlipPage() protected override void OnFlipPage()
{ {
base.OnFlipPage(); base.OnFlipPage();
// 刷新所有成员的层级顺序 // 刷新所有成员的层级顺序
for (int i = 0; i < pageSelectButton.Count; i++) for (int i = 0; i < pageSelectButton.Count; i++)
{ {
pageSelectButton[i].Target0.transform.SetSiblingIndex(i); pageSelectButton[i].Target0.transform.SetSiblingIndex(i);
} }
if (Currentpage is PageComponentInfo componentPage &&
componentPage.pageSelectableVessel.IsValidVessel())
{
SwitchSelectableVesselType(componentPage.pageSelectableVessel.Target0,
null,
toggle =>
{
if (!toggle.isOn)
toggle.isOn = true;
});
}
} }
public override void FlipPage(int pageIndex, bool forceRefresh = false) public override void FlipPage(int pageIndex, bool forceRefresh = false)
{ {
base.FlipPage(pageIndex, forceRefresh); base.FlipPage(pageIndex, forceRefresh);
}
public override void AddPageFirst(PageInfo pageInfo)
{
if (pageInfo is not PageComponentInfo componentPageInfo)
{
Debug.LogError($"页面容器{currentPage}不支持当前管理器,其必须由{nameof(FlipPageComponentManager)}.{nameof(PageComponentInfo)}继承/声名,否则无法支持后续功能", this);
return;
}
AddPageIndexButton(componentPageInfo);
base.AddPageFirst(pageInfo);
RefreshLabelTextTotalPageCount();
RefreshPageIndeButtonState(); RefreshPageIndeButtonState();
} }
public override void AddPageLast(PageInfo pageInfo) public override PageInfo AddPageFirst(PageInfo pageInfo)
{ {
if (pageInfo is not PageComponentInfo componentPageInfo) if (pageInfo is not PageComponentInfo componentPageInfo)
{ {
Debug.LogError($"页面容器{currentPage}不支持当前管理器,其必须由{nameof(FlipPageComponentManager)}.{nameof(PageComponentInfo)}继承/声名,否则无法支持后续功能", this); Debug.LogError($"页面容器{Currentpage}不支持当前管理器,其必须由{nameof(FlipPageComponentManager)}.{nameof(PageComponentInfo)}继承/声名,否则无法支持后续功能", this);
return; return null;
} }
// 页面基础初始化
var result = base.AddPageFirst(pageInfo);
// 添加选择按钮
AddPageIndexButton(componentPageInfo); AddPageIndexButton(componentPageInfo);
base.AddPageLast(pageInfo); // 刷新选择按钮显示状态
RefreshLabelTextTotalPageCount();
RefreshPageIndeButtonState(); RefreshPageIndeButtonState();
// 刷新总页数
RefreshLabelTextTotalPageCount();
return result;
}
public override PageInfo AddPageLast(PageInfo pageInfo)
{
if (pageInfo is not PageComponentInfo componentPageInfo)
{
Debug.LogError($"页面容器{Currentpage}不支持当前管理器,其必须由{nameof(FlipPageComponentManager)}.{nameof(PageComponentInfo)}继承/声名,否则无法支持后续功能", this);
return null;
}
// 页面基础初始化
var result = base.AddPageLast(pageInfo);
// 添加选择按钮
AddPageIndexButton(componentPageInfo);
// 刷新选择按钮显示状态
RefreshPageIndeButtonState();
// 刷新总页数
RefreshLabelTextTotalPageCount();
return result;
} }
public override void RemovePage(int pageIndex) public override void RemovePage(int pageIndex)
{ {
base.RemovePage(pageIndex); base.RemovePage(pageIndex);
pageButtonPool.DirectlyRelease(pageSelectButton[pageIndex].Target0.gameObject); pageButtonPool.DirectlyRelease(pageSelectButton[pageIndex].Target0.gameObject);
pageSelectButton.RemoveAt(pageIndex); pageSelectButton.RemoveAt(pageIndex);
RefreshPageIndeButtonState(); RefreshPageIndeButtonState();
} }
public override void ClearPages()
{
foreach (var pageInfo in PageInfos)
{
var page = pageInfo as PageComponentInfo;
pageButtonPool.DirectlyRelease(page.pageSelectableVessel.Target0.gameObject);
}
pageSelectButton.Clear();
base.ClearPages();
}
/// <summary> /// <summary>
/// 在页面上添加按钮 /// 在页面上添加按钮
/// </summary> /// </summary>
/// <param name="pageInfo"></param> /// <param name="pageInfo"></param>
private void AddPageIndexButton(PageComponentInfo pageInfo) protected virtual void AddPageIndexButton(PageComponentInfo pageInfo)
{ {
var pageIndexSelectable = GetPageIndexButton(); var pageIndexSelectable = GetPageIndexButton();
pageInfo.pageIndexSelectable = pageIndexSelectable; pageInfo.pageSelectableVessel = pageIndexSelectable;
// 将按钮对象添加到列表中便于管理
pageSelectButton.Add(pageIndexSelectable);
SwitchSelectableVesselType(pageIndexSelectable.Target0,
button =>
{
button.onClick.AddListener(() => FlipPage(pageInfo.pageNumber));
},
toggle =>
{
toggle.isOn = pageInfo.pageNumber == currentPageIndex;
toggle.group = ToggleGroup;
toggle.onValueChanged.AddListener(b =>
{
if (b)
FlipPage(pageInfo.pageNumber);
});
});
RefreshPageSelectableVesselLabel(pageInfo);
} }
/// <summary> /// <summary>
@@ -289,8 +347,14 @@ namespace XericUI.FlipPage
/// </summary> /// </summary>
private void RefreshPageIndeButtonState() private void RefreshPageIndeButtonState()
{ {
var min = currentPageIndex - candidatesNumber / 2; var min = currentPageIndex - (int)(candidatesNumber / 2);
var max = currentPageIndex + candidatesNumber / 2;
min = Math.Max(min, 0);
min = pageSelectButton.Count - candidatesNumber > 0
? Math.Min(min, (int)(pageSelectButton.Count - candidatesNumber))
: 0;
var max = min + (int)candidatesNumber;
for (int i = 0; i < pageSelectButton.Count; i++) for (int i = 0; i < pageSelectButton.Count; i++)
{ {
pageSelectButton[i].Target0.transform.SetSiblingIndex(i); pageSelectButton[i].Target0.transform.SetSiblingIndex(i);
@@ -299,13 +363,20 @@ namespace XericUI.FlipPage
if (inMaximumCandidatesNumber) if (inMaximumCandidatesNumber)
pageSelectButton[i].Target0.gameObject.SetActive(min <= i && i <= max); pageSelectButton[i].Target0.gameObject.SetActive(min <= i && i <= max);
else else
pageSelectButton[i].Target0.gameObject.SetActive(min < i && i < max); pageSelectButton[i].Target0.gameObject.SetActive(min <= i && i < max);
// 看不见的内容不刷新
if (!pageSelectButton[i].Target0.gameObject.activeSelf)
continue;
// 更新索引 // 更新索引
if (pageSelectButton[i].Target0.gameObject.activeSelf) pageSelectButton[i].Target1.text = MacroRegex.RegexReplace(pageIndexFormat, i + 1);
{
pageSelectButton[i].Target1.text = MacroRegex.RegexReplace(pageIndexFormat, i); // SwitchSelectableVesselType(pageSelectButton[i].Target0,
} // null,
// toggle =>
// {
// toggle.SetIsOnWithoutNotify(currentPageIndex == i);
// });
} }
} }
@@ -315,7 +386,18 @@ namespace XericUI.FlipPage
private void RefreshLabelTextTotalPageCount() private void RefreshLabelTextTotalPageCount()
{ {
if (labelTextTotalPageCount.IsValidVessel()) // 总页数更新 if (labelTextTotalPageCount.IsValidVessel()) // 总页数更新
labelTextTotalPageCount.Target.text = MacroRegex.RegexReplace(totalPageCountFormat, PageInfos.Count.ToString()); labelTextTotalPageCount.Target.text =
MacroRegex.RegexReplace(totalPageCountFormat, PageInfos.Count.ToString());
}
/// <summary>
/// 刷新翻页按钮索引为当前页面索引
/// </summary>
public void RefreshPageSelectableVesselLabel(PageComponentInfo page, object customInput = null)
{
if (page.pageSelectableVessel.IsValidVessel())
page.pageSelectableVessel!.Target1.text =
MacroRegex.RegexReplace(pageIndexFormat, customInput ?? page.pageNumber);
} }
#endregion #endregion
@@ -345,7 +427,33 @@ namespace XericUI.FlipPage
}); });
} }
} }
/// <summary>
/// 处理可选对象类型,如果要支持更多的类型优先改此方法,以便获得其他所有位置的编译器提示
/// </summary>
/// <param name="selectable"></param>
/// <param name="asButton"></param>
/// <param name="asToggle"></param>
/// <returns></returns>
protected static bool SwitchSelectableVesselType(Selectable selectable, Action<Button> asButton, Action<Toggle> asToggle)
{
switch (selectable)
{
case CircleSlider circleSlider: break; // asCircleSlider?.Invoke(circleSlider); break;
case TMP_Dropdown tmpDropdown: break; // asTmpDropdown?.Invoke(tmpDropdown); break;
case TMP_InputField tmpInputField: break; // asTmpInputField?.Invoke(tmpInputField); break;
case Button button: asButton?.Invoke(button); return true;
case Dropdown dropdown: break; // asDropdown?.Invoke(dropdown); break;
case InputField inputField: break; // asInputField?.Invoke(inputField); break;
case Scrollbar scrollbar: break; // asScrollbar?.Invoke(scrollbar); break;
case Slider slider: break; // asSlider?.Invoke(slider); break;
case Toggle toggle: asToggle?.Invoke(toggle); return true;
default: break;
}
Debug.LogError($"目前不支持的可选类型:{selectable}");
return false;
}
#endregion #endregion
} }
} }
+237 -32
View File
@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization; using UnityEngine.Serialization;
@@ -49,7 +50,7 @@ namespace XericUI.FlipPage
[BoxGroup("设定")] [BoxGroup("设定")]
#endif #endif
[SerializeField] [SerializeField]
protected int defaultItemCountPerPage = -1; private int defaultItemCountPerPage = -1;
#endregion #endregion
@@ -91,6 +92,22 @@ namespace XericUI.FlipPage
#region 生命周期 #region 生命周期
/// <summary>
/// 页面创建时
/// </summary>
protected internal virtual void OnPageCreated(XericFlipPageIndexVesselBase parent)
{
}
/// <summary>
/// 页面销毁时
/// </summary>
protected internal virtual void OnPageDestroy(XericFlipPageIndexVesselBase parent)
{
}
/// <summary> /// <summary>
/// 页面显示时 /// 页面显示时
/// </summary> /// </summary>
@@ -102,7 +119,7 @@ namespace XericUI.FlipPage
/// </summary> /// </summary>
/// <param name="quickVisit">快速浏览(用于区分动画和逻辑,为真时,不应当在动画事件后继续加载数据)</param> /// <param name="quickVisit">快速浏览(用于区分动画和逻辑,为真时,不应当在动画事件后继续加载数据)</param>
protected internal abstract void OnPageInvisible(bool quickVisit); protected internal abstract void OnPageInvisible(bool quickVisit);
#endregion #endregion
public override string ToString() public override string ToString()
@@ -124,6 +141,14 @@ namespace XericUI.FlipPage
#endif #endif
public string name = DateTime.Now.Ticks.ToString(); public string name = DateTime.Now.Ticks.ToString();
/// <summary>
/// 从零开始计数的项目下标
/// </summary>
#if ODIN_INSPECTOR
[LabelText("项目索引[0, n]")]
#endif
public int itemNumber { get; internal set; }
#endregion #endregion
#region 生命周期 #region 生命周期
@@ -159,9 +184,20 @@ namespace XericUI.FlipPage
[SerializeField] [SerializeField]
protected int currentPageIndex = 0; protected int currentPageIndex = 0;
#if UNITY_EDITOR
/// <summary>
/// 显示调试列表
/// </summary>
#if ODIN_INSPECTOR
[ShowInInspector]
#endif
private List<PageInfo> PageInfoLists => _pageInfos.ToList();
#endif
/// <summary> /// <summary>
/// 所有页面 /// 所有页面
/// </summary> /// </summary>
private LinkedList<PageInfo> _pageInfos = new LinkedList<PageInfo>(); private LinkedList<PageInfo> _pageInfos = new LinkedList<PageInfo>();
/// <summary> /// <summary>
@@ -169,11 +205,11 @@ namespace XericUI.FlipPage
/// </summary> /// </summary>
private HashSet<ItemInfo> _itemInfos = new HashSet<ItemInfo>(); private HashSet<ItemInfo> _itemInfos = new HashSet<ItemInfo>();
/// <summary> /// <summary>
/// 当前选中页面节点 /// 当前选中页面节点
/// </summary> /// </summary>
public LinkedListNode<PageInfo> currentPageNode = null; protected LinkedListNode<PageInfo> CurrentPageNode = null;
/// <summary> /// <summary>
/// 所有页面 /// 所有页面
@@ -183,7 +219,21 @@ namespace XericUI.FlipPage
/// <summary> /// <summary>
/// 当前选中页面内容 /// 当前选中页面内容
/// </summary> /// </summary>
public PageInfo currentPage => currentPageNode.Value; public PageInfo Currentpage => CurrentPageNode?.Value;
/// <summary>
/// 分布于所有页面上的所有数据项目
/// </summary>
public IEnumerable<ItemInfo> AllItemInfos => _pageInfos.SelectMany(page => page.itemInfos);
/// <summary>
/// 页面默认最大项目数量
/// </summary>
protected int DefaultItemCountPerPage
=> defaultItemCountPerPage < 0 ? int.MaxValue : defaultItemCountPerPage;
private List<ItemInfo> _backupItemInfos;
#endregion #endregion
@@ -222,7 +272,7 @@ namespace XericUI.FlipPage
{ {
if (float.TryParse(pageNumber, out var index)) if (float.TryParse(pageNumber, out var index))
{ {
FlipPage((int)index, forceRefresh); FlipPage((int)index - 1, forceRefresh);
} }
} }
@@ -239,7 +289,7 @@ namespace XericUI.FlipPage
(pageIndex < 0 || pageIndex >= _pageInfos.Count)) (pageIndex < 0 || pageIndex >= _pageInfos.Count))
pageIndex = Mathf.Clamp(pageIndex, 0, _pageInfos.Count - 1); pageIndex = Mathf.Clamp(pageIndex, 0, _pageInfos.Count - 1);
else else
pageIndex = MacroMath.PMod(pageIndex, _pageInfos.Count - 1); pageIndex = MacroMath.PMod(pageIndex, _pageInfos.Count);
// 检查翻页数量有效 // 检查翻页数量有效
if (!forceRefresh && currentPageIndex == pageIndex) if (!forceRefresh && currentPageIndex == pageIndex)
return; return;
@@ -247,23 +297,23 @@ namespace XericUI.FlipPage
var pageIndexOffset = pageIndex - currentPageIndex; var pageIndexOffset = pageIndex - currentPageIndex;
var lastPageIndex = currentPageIndex; var lastPageIndex = currentPageIndex;
// 如果节点不存在,通过索引寻找 // 如果节点不存在,通过索引寻找
if (currentPageNode == null) if (CurrentPageNode == null)
currentPageNode = _pageInfos.GetOrderNode().LandedIndex(currentPageIndex); CurrentPageNode = _pageInfos.GetOrderNode().LandedIndex(currentPageIndex);
// 如果索引偏移,逐个移动 // 如果索引偏移,逐个移动
else if (pageIndexOffset > 0) else if (pageIndexOffset > 0)
{ {
for (var i = 0; i < pageIndexOffset; i++) for (var i = 0; i < pageIndexOffset; i++)
{ {
var next = currentPageNode!.Next; var next = CurrentPageNode!.Next;
SwitchPage(next, _pageInfos.Last, i + 1 == pageIndexOffset); SwitchPage(next, _pageInfos.Last, i + 1 < pageIndexOffset);
} }
} }
else if (pageIndexOffset < 0) else if (pageIndexOffset < 0)
{ {
for (var i = 0; i > pageIndexOffset; i--) for (var i = 0; i > pageIndexOffset; i--)
{ {
var previa = currentPageNode!.Previous; var previa = CurrentPageNode!.Previous;
SwitchPage(previa, _pageInfos.First, i - 1 == pageIndexOffset); SwitchPage(previa, _pageInfos.First, i - 1 > pageIndexOffset);
} }
} }
// 没有翻动有效页,退出 // 没有翻动有效页,退出
@@ -278,16 +328,16 @@ namespace XericUI.FlipPage
{ {
if (newPageNode != null) if (newPageNode != null)
{ {
currentPage.OnPageInvisible(quickPage); Currentpage.OnPageInvisible(quickPage);
currentPageNode = newPageNode; CurrentPageNode = newPageNode;
currentPage.OnPageVisible(quickPage); Currentpage.OnPageVisible(quickPage);
} }
if (canPassIndexBoundary) if (canPassIndexBoundary)
{ {
currentPage.OnPageInvisible(quickPage); Currentpage.OnPageInvisible(quickPage);
currentPageNode = defualtPageNode; CurrentPageNode = defualtPageNode;
currentPage.OnPageVisible(quickPage); Currentpage.OnPageVisible(quickPage);
} }
} }
} }
@@ -331,44 +381,49 @@ namespace XericUI.FlipPage
/// <summary> /// <summary>
/// 添加页面在开头 /// 添加页面在开头
/// </summary> /// </summary>
public virtual void AddPageFirst(PageInfo pageInfo) public virtual PageInfo AddPageFirst(PageInfo pageInfo)
{ {
if (pageInfo == null) if (pageInfo == null)
{ {
Debug.LogError($"不能添加一个空的页面内容到管理器中!", this); Debug.LogError($"不能添加一个空的页面内容到管理器中!", this);
return; return null;
} }
// 添加页面
_pageInfos.AddFirst(pageInfo);
// 添加页面下标 // 添加页面下标
pageInfo.pageNumber = 0; pageInfo.pageNumber = 0;
// 添加页面
_pageInfos.AddFirst(pageInfo);
// 更新后面页面的索引 // 更新后面页面的索引
RefreshAllPageNumber(); RefreshAllPageNumber();
// 执行页面生命周期
pageInfo.OnPageCreated(this);
// 刷新页面 // 刷新页面
FlipPage(currentPageIndex, true); FlipPage(currentPageIndex, true);
return pageInfo;
} }
/// <summary> /// <summary>
/// 添加页面在结尾 /// 添加页面在结尾
/// </summary> /// </summary>
public virtual void AddPageLast(PageInfo pageInfo) public virtual PageInfo AddPageLast(PageInfo pageInfo)
{ {
if (pageInfo == null) if (pageInfo == null)
{ {
Debug.LogError($"不能添加一个空的页面内容到管理器中!", this); Debug.LogError($"不能添加一个空的页面内容到管理器中!", this);
return; return null;
} }
// 添加页面下标 // 添加页面下标
pageInfo.pageNumber = _pageInfos.Count; pageInfo.pageNumber = _pageInfos.Count;
// 添加页面 // 添加页面
_pageInfos.AddLast(pageInfo); _pageInfos.AddLast(pageInfo);
// 执行页面生命周期
pageInfo.OnPageDestroy(this);
// 刷新页面 // 刷新页面
FlipPage(currentPageIndex, true); FlipPage(currentPageIndex, true);
return pageInfo;
} }
/// <summary> /// <summary>
/// 移除页面 /// 移除页面(页面上的数据内容也会一同移除)
/// </summary> /// </summary>
public virtual void RemovePage(int pageIndex) public virtual void RemovePage(int pageIndex)
{ {
@@ -388,23 +443,50 @@ namespace XericUI.FlipPage
tempPage.Value.pageNumber = tempPageNumber++; tempPage.Value.pageNumber = tempPageNumber++;
} }
// 如果移除的是当前页面,执行关闭操作 // 如果移除的是当前页面,执行关闭操作
if (currentPageNode == page) if (CurrentPageNode == page)
{ {
page.Value.OnPageInvisible(true); page.Value.OnPageInvisible(true);
currentPageNode = null; CurrentPageNode = null;
} }
// 执行页面生命周期
page.Value.OnPageDestroy(this);
// 页面索引移除
_pageInfos.Remove(page); _pageInfos.Remove(page);
// 刷新页面 // 刷新页面
FlipPage(currentPageIndex, true); FlipPage(currentPageIndex, true);
} }
/// <summary> /// <summary>
/// 清除所有页面 /// 仅移除页面,不会移除数据
/// </summary> /// </summary>
public virtual void CleanPage() /// <param name="pageIndex"></param>
public void RemovePageWithoutItems(int pageIndex)
{
BackupItemsFormPages();
RemovePage(pageIndex);
RestoreItemsToPages();
}
/// <summary>
/// 获取索引下的页面
/// </summary>
/// <param name="pageIndex"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T IndexOfPageInfo<T>(int pageIndex)
where T : PageInfo
=> _pageInfos.LandedIndex(pageIndex) as T;
/// <summary>
/// 清除所有页面 (所有页面数据也会一同移除)
/// </summary>
#if ODIN_INSPECTOR
[HorizontalGroup("数据"), Button("清除所有页面")]
#endif
public virtual void ClearPages()
{ {
_pageInfos.Clear(); _pageInfos.Clear();
currentPageNode = null; CurrentPageNode = null;
currentPageIndex = 0; currentPageIndex = 0;
} }
@@ -436,5 +518,128 @@ namespace XericUI.FlipPage
} }
#endregion #endregion
#region 数据项目
/// <summary>
/// 添加数据项目
/// </summary>
public void AddItem(ItemInfo item, Func<PageInfo> addPage)
{
// 向前寻找空缺(这在页面都被准确填充的情况下最忧)
var firstVacancy = _pageInfos
.GetReversedOrderNode()
.LastOrDefault(a
=> a.Value.itemInfos.Count < DefaultItemCountPerPage);
if (firstVacancy != null)
{
firstVacancy.Value.itemInfos.Add(item);
return;
}
if (addPage == null)
{
Debug.LogError("当前页面已满,数据项目顺位添加到新页面中,但未指定页面创建函数,添加过程已退出", this);
return;
}
// 新建一个页面存放数据
addPage.Invoke().itemInfos.Add(item);
}
/// <summary>
/// 移除所有包含给定项目的位置(这会在页面上留下空缺)
/// </summary>
/// <param name="item"></param>
public void RemoveItem(ItemInfo item)
{
foreach (var a in AllItemInfos
.Adjoint()
.Where(a => a.obj == item)
.Reverse())
{
ItemIndex2PageIndex(a.index);
}
}
public void RemoveItem(int indexItem)
{
}
/// <summary>
/// 保留页面的状态下清空所有数据
/// </summary>
#if ODIN_INSPECTOR
[HorizontalGroup("数据"), Button("清除所有数据")]
#endif
public void ClearItemsWithoutPages()
{
foreach (var page in _pageInfos)
{
page.itemInfos.Clear();
}
}
/// <summary>
/// 使用索引定位到数据
/// </summary>
/// <param name="itemIndex"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T IndexOfItemInfo<T>(int itemIndex)
where T : ItemInfo
=> AllItemInfos.LandedIndex(itemIndex) as T;
/// <summary>
/// 将项目索引转为页面索引
/// </summary>
/// <param name="itemIndex"></param>
/// <returns></returns>
public virtual int ItemIndex2PageIndex(int itemIndex)
{
return itemIndex / DefaultItemCountPerPage;
}
/// <summary>
/// 备份所有数据项目
/// </summary>
public void BackupItemsFormPages()
{
_backupItemInfos = AllItemInfos.ToList();
}
/// <summary>
/// 保存所有数据项目(强制重排操作)
/// </summary>
public void RestoreItemsToPages()
{
if (ItemIndex2PageIndex(_backupItemInfos.Count - 1) > _pageInfos.Count)
{
Debug.LogError($"重排数据时,原有数据数量({_backupItemInfos.Count})超出现有面板数量({_pageInfos.Count}),已拒绝重排", this);
return;
}
// 执行重拍
var page = _pageInfos.First;
page.Value.itemInfos.Clear();
var pageIndex = 0;
for (int i = 0; i < _backupItemInfos.Count; i++)
{
var newPageIndex = ItemIndex2PageIndex(i);
if (pageIndex != newPageIndex)
{
pageIndex = newPageIndex;
page = page.Next;
if (page == null)
{
Debug.LogError($"重排数据时,页面链接错误,重排被迫中断", this);
return;
}
page.Value.itemInfos.Clear();
}
page.Value.itemInfos.Add(_backupItemInfos[i]);
}
}
#endregion
} }
} }