暂存翻页容器相关内容
This commit is contained in:
@@ -10,7 +10,7 @@ namespace XericUI.Core.Vessel
|
|||||||
/// <param name="obj"></param>
|
/// <param name="obj"></param>
|
||||||
/// <typeparam name="T0"></typeparam>
|
/// <typeparam name="T0"></typeparam>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool IsValid<T0>(this ObjectVessel<T0> obj)
|
public static bool IsValidVessel<T0>(this ObjectVessel<T0> obj)
|
||||||
where T0 : Object
|
where T0 : Object
|
||||||
=> obj != null && obj.Target != null;
|
=> obj != null && obj.Target != null;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -20,7 +20,7 @@ namespace XericUI.Core.Vessel
|
|||||||
/// <typeparam name="T0"></typeparam>
|
/// <typeparam name="T0"></typeparam>
|
||||||
/// <typeparam name="T1"></typeparam>
|
/// <typeparam name="T1"></typeparam>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool IsValid<T0, T1>(this ObjectVessel<T0, T1> obj)
|
public static bool IsValidVessel<T0, T1>(this ObjectVessel<T0, T1> obj)
|
||||||
where T0 : Object
|
where T0 : Object
|
||||||
where T1 : Object
|
where T1 : Object
|
||||||
=> obj != null && obj.Target0 != null && obj.Target1 != null;
|
=> obj != null && obj.Target0 != null && obj.Target1 != null;
|
||||||
@@ -32,7 +32,7 @@ namespace XericUI.Core.Vessel
|
|||||||
/// <typeparam name="T1"></typeparam>
|
/// <typeparam name="T1"></typeparam>
|
||||||
/// <typeparam name="T2"></typeparam>
|
/// <typeparam name="T2"></typeparam>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool IsValid<T0, T1, T2>(this ObjectVessel<T0, T1, T2> obj)
|
public static bool IsValidVessel<T0, T1, T2>(this ObjectVessel<T0, T1, T2> obj)
|
||||||
where T0 : Object
|
where T0 : Object
|
||||||
where T1 : Object
|
where T1 : Object
|
||||||
where T2 : Object
|
where T2 : Object
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Sirenix.OdinInspector;
|
using Sirenix.OdinInspector;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using XericLibrary.Runtime.MacroLibrary;
|
||||||
using XericUI.Core.Vessel;
|
using XericUI.Core.Vessel;
|
||||||
|
using Component = UnityEngine.Component;
|
||||||
|
|
||||||
namespace XericUI.FlipPage
|
namespace XericUI.FlipPage
|
||||||
{
|
{
|
||||||
@@ -16,6 +20,17 @@ namespace XericUI.FlipPage
|
|||||||
{
|
{
|
||||||
#region 界面属性
|
#region 界面属性
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 候选页数量
|
||||||
|
/// </summary>
|
||||||
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("候选页按最多显示")]
|
||||||
|
[BoxGroup("设定", centerLabel: true)]
|
||||||
|
#endif
|
||||||
|
[Tooltip("候选页按最多数量展示")]
|
||||||
|
[SerializeField]
|
||||||
|
protected bool inMaximumCandidatesNumber = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 首页按钮
|
/// 首页按钮
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -52,20 +67,38 @@ namespace XericUI.FlipPage
|
|||||||
/// 总页面数量文本
|
/// 总页面数量文本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#if ODIN_INSPECTOR
|
#if ODIN_INSPECTOR
|
||||||
|
[Space(2)]
|
||||||
[LabelText("总页面数量文本")] [BoxGroup("组件")]
|
[LabelText("总页面数量文本")] [BoxGroup("组件")]
|
||||||
#endif
|
#endif
|
||||||
public ObjectVessel<TMPro.TMP_Text> labelTextTotalPageCount =
|
public ObjectVessel<TMPro.TMP_Text> labelTextTotalPageCount =
|
||||||
new ObjectVessel<TMPro.TMP_Text>();
|
new ObjectVessel<TMPro.TMP_Text>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 总页面数量文本
|
/// 总页面数量文本格式化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#if ODIN_INSPECTOR
|
#if ODIN_INSPECTOR
|
||||||
[LabelText("总页面数量文本")] [BoxGroup("组件")]
|
[LabelText("总页面数量文本格式化")] [BoxGroup("设定")]
|
||||||
|
#endif
|
||||||
|
public string totalPageCountFormat = "共$1页";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面索引文本格式化
|
||||||
|
/// </summary>
|
||||||
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("页面索引文本格式化")] [BoxGroup("设定")]
|
||||||
|
#endif
|
||||||
|
public string pageIndexFormat = "$1";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面选择组件列表
|
||||||
|
/// </summary>
|
||||||
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("页面选择组件列表")] [BoxGroup("组件")]
|
||||||
// [ListDrawerSettings(ShowIndexLabels = true)]
|
// [ListDrawerSettings(ShowIndexLabels = true)]
|
||||||
#endif
|
#endif
|
||||||
public List<ObjectVessel<Button, TMPro.TMP_Text>> pageSelectButton =
|
[Tooltip("首个组件应当作为主要的节点管理")]
|
||||||
new List<ObjectVessel<Button, TMPro.TMP_Text>>();
|
public List<ObjectVessel<Selectable, TMPro.TMP_Text>> pageSelectButton =
|
||||||
|
new List<ObjectVessel<Selectable, TMPro.TMP_Text>>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 页面跳转输入框
|
/// 页面跳转输入框
|
||||||
@@ -73,8 +106,7 @@ namespace XericUI.FlipPage
|
|||||||
#if ODIN_INSPECTOR
|
#if ODIN_INSPECTOR
|
||||||
[LabelText("页面跳转输入框")] [BoxGroup("组件")]
|
[LabelText("页面跳转输入框")] [BoxGroup("组件")]
|
||||||
#endif
|
#endif
|
||||||
public ObjectVessel<TMPro.TMP_InputField> inputFieldFlipPageIndex =
|
public ObjectVessel<TMPro.TMP_InputField> inputFieldFlipPageIndex;
|
||||||
new ObjectVessel<TMPro.TMP_InputField>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 翻页到索引按钮池
|
/// 翻页到索引按钮池
|
||||||
@@ -86,26 +118,114 @@ namespace XericUI.FlipPage
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 字段属性
|
||||||
|
|
||||||
|
protected ToggleGroup ToggleGroup;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 类内类型
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面与组件信息
|
||||||
|
/// </summary>
|
||||||
|
public class PageComponentInfo : PageInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 页面翻页按钮
|
||||||
|
/// </summary>
|
||||||
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("页面翻页按钮")]
|
||||||
|
#endif
|
||||||
|
[CanBeNull]
|
||||||
|
internal ObjectVessel<Selectable, TMPro.TMP_Text> pageIndexSelectable;
|
||||||
|
|
||||||
|
protected internal override void OnPageVisible(bool quickVisit)
|
||||||
|
{
|
||||||
|
if (quickVisit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 自动补全外部交互动画
|
||||||
|
if (pageIndexSelectable.IsValidVessel() &&
|
||||||
|
pageIndexSelectable.Target0 is Toggle toggle &&
|
||||||
|
!toggle.isOn)
|
||||||
|
{
|
||||||
|
toggle.SetIsOnWithoutNotify(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal override void OnPageInvisible(bool quickVisit)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 项目与组件信息
|
||||||
|
/// </summary>
|
||||||
|
public class ItemComponentInfo : ItemInfo
|
||||||
|
{
|
||||||
|
protected internal override void OnItemVisible()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected internal override void OnItemInvisible()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region 生命周期
|
#region 生命周期
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
protected override void OnValidate()
|
||||||
|
{
|
||||||
|
base.OnValidate();
|
||||||
|
// pageButtonPool.Prefab.GetComponent<Selectable>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
protected override void Awake()
|
protected override void Awake()
|
||||||
{
|
{
|
||||||
base.Awake();
|
base.Awake();
|
||||||
if (buttonStartPage.IsValid()) // 翻到开头
|
if (buttonStartPage.IsValidVessel()) // 翻到开头
|
||||||
buttonStartPage.Target.onClick.AddListener(FlipPageToStart);
|
buttonStartPage.Target.onClick.AddListener(FlipPageToStart);
|
||||||
if (buttonPreviousPage.IsValid()) // 翻到上一页
|
if (buttonPreviousPage.IsValidVessel()) // 翻到上一页
|
||||||
buttonPreviousPage.Target.onClick.AddListener(FlipPageToPrevious);
|
buttonPreviousPage.Target.onClick.AddListener(FlipPageToPrevious);
|
||||||
if (buttonNextPage.IsValid()) // 翻到下一页
|
if (buttonNextPage.IsValidVessel()) // 翻到下一页
|
||||||
buttonNextPage.Target.onClick.AddListener(FlipPageToNext);
|
buttonNextPage.Target.onClick.AddListener(FlipPageToNext);
|
||||||
if (buttoneEndPage.IsValid()) // 翻到结尾
|
if (buttoneEndPage.IsValidVessel()) // 翻到结尾
|
||||||
buttoneEndPage.Target.onClick.AddListener(FlipPageToEnd);
|
buttoneEndPage.Target.onClick.AddListener(FlipPageToEnd);
|
||||||
|
if (inputFieldFlipPageIndex.IsValidVessel()) // 翻到指定
|
||||||
|
inputFieldFlipPageIndex.Target.onValueChanged.AddListener(s => FlipPage(s));
|
||||||
pageButtonPool.Init();
|
pageButtonPool.Init();
|
||||||
|
|
||||||
|
// 根据组件类型创建相关内容
|
||||||
|
var prefabSelectable = pageButtonPool.Prefab.GetComponent<Selectable>();
|
||||||
|
switch (prefabSelectable)
|
||||||
|
{
|
||||||
|
// 单选项就创建但选项组
|
||||||
|
case Toggle toggle:
|
||||||
|
ToggleGroup = transform.GetComponentAnyway<ToggleGroup>();
|
||||||
|
break;
|
||||||
|
case Button button:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
protected override void OnFlipPage()
|
||||||
{
|
{
|
||||||
if (labelTextTotalPageCount.IsValid()) // 页数
|
base.OnFlipPage();
|
||||||
labelTextTotalPageCount.Target.text = PageInfos.Count.ToString();
|
|
||||||
|
|
||||||
|
// 刷新所有成员的层级顺序
|
||||||
|
for (int i = 0; i < pageSelectButton.Count; i++)
|
||||||
|
{
|
||||||
|
pageSelectButton[i].Target0.transform.SetSiblingIndex(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void FlipPage(int pageIndex, bool forceRefresh = false)
|
public override void FlipPage(int pageIndex, bool forceRefresh = false)
|
||||||
@@ -114,10 +234,88 @@ namespace XericUI.FlipPage
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AddPage(PageInfo pageInfo)
|
public override void AddPageFirst(PageInfo pageInfo)
|
||||||
{
|
{
|
||||||
base.AddPage(pageInfo);
|
if (pageInfo is not PageComponentInfo componentPageInfo)
|
||||||
pageSelectButton.Add(GetPageIndexButton());
|
{
|
||||||
|
Debug.LogError($"页面容器{currentPage}不支持当前管理器,其必须由{nameof(FlipPageComponentManager)}.{nameof(PageComponentInfo)}继承/声名,否则无法支持后续功能", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddPageIndexButton(componentPageInfo);
|
||||||
|
base.AddPageFirst(pageInfo);
|
||||||
|
|
||||||
|
RefreshLabelTextTotalPageCount();
|
||||||
|
RefreshPageIndeButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddPageLast(PageInfo pageInfo)
|
||||||
|
{
|
||||||
|
if (pageInfo is not PageComponentInfo componentPageInfo)
|
||||||
|
{
|
||||||
|
Debug.LogError($"页面容器{currentPage}不支持当前管理器,其必须由{nameof(FlipPageComponentManager)}.{nameof(PageComponentInfo)}继承/声名,否则无法支持后续功能", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddPageIndexButton(componentPageInfo);
|
||||||
|
base.AddPageLast(pageInfo);
|
||||||
|
|
||||||
|
RefreshLabelTextTotalPageCount();
|
||||||
|
RefreshPageIndeButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void RemovePage(int pageIndex)
|
||||||
|
{
|
||||||
|
base.RemovePage(pageIndex);
|
||||||
|
|
||||||
|
pageButtonPool.DirectlyRelease(pageSelectButton[pageIndex].Target0.gameObject);
|
||||||
|
pageSelectButton.RemoveAt(pageIndex);
|
||||||
|
|
||||||
|
RefreshPageIndeButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在页面上添加按钮
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pageInfo"></param>
|
||||||
|
private void AddPageIndexButton(PageComponentInfo pageInfo)
|
||||||
|
{
|
||||||
|
var pageIndexSelectable = GetPageIndexButton();
|
||||||
|
pageInfo.pageIndexSelectable = pageIndexSelectable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 刷新所有页面按钮的可见性,索引
|
||||||
|
/// </summary>
|
||||||
|
private void RefreshPageIndeButtonState()
|
||||||
|
{
|
||||||
|
var min = currentPageIndex - candidatesNumber / 2;
|
||||||
|
var max = currentPageIndex + candidatesNumber / 2;
|
||||||
|
for (int i = 0; i < pageSelectButton.Count; i++)
|
||||||
|
{
|
||||||
|
pageSelectButton[i].Target0.transform.SetSiblingIndex(i);
|
||||||
|
|
||||||
|
// 显示数量控制
|
||||||
|
if (inMaximumCandidatesNumber)
|
||||||
|
pageSelectButton[i].Target0.gameObject.SetActive(min <= i && i <= max);
|
||||||
|
else
|
||||||
|
pageSelectButton[i].Target0.gameObject.SetActive(min < i && i < max);
|
||||||
|
|
||||||
|
// 更新索引
|
||||||
|
if (pageSelectButton[i].Target0.gameObject.activeSelf)
|
||||||
|
{
|
||||||
|
pageSelectButton[i].Target1.text = MacroRegex.RegexReplace(pageIndexFormat, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新总页数
|
||||||
|
/// </summary>
|
||||||
|
private void RefreshLabelTextTotalPageCount()
|
||||||
|
{
|
||||||
|
if (labelTextTotalPageCount.IsValidVessel()) // 总页数更新
|
||||||
|
labelTextTotalPageCount.Target.text = MacroRegex.RegexReplace(totalPageCountFormat, PageInfos.Count.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -128,24 +326,26 @@ namespace XericUI.FlipPage
|
|||||||
/// 获取页面索引按钮
|
/// 获取页面索引按钮
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected virtual ObjectVessel<Button, TMPro.TMP_Text> GetPageIndexButton()
|
protected virtual ObjectVessel<Selectable, TMPro.TMP_Text> GetPageIndexButton()
|
||||||
{
|
{
|
||||||
var obj = pageButtonPool.Get();
|
var obj = pageButtonPool.Get();
|
||||||
var button = obj.GetComponent<Button>() ?? obj.GetComponentInChildren<Button>();
|
var selectable = obj.GetComponent<Selectable>() ?? obj.GetComponentInChildren<Selectable>();
|
||||||
var text = obj.GetComponent<TMPro.TMP_Text>() ?? obj.GetComponentInChildren<TMPro.TMP_Text>();
|
var text = obj.GetComponent<TMPro.TMP_Text>() ?? obj.GetComponentInChildren<TMPro.TMP_Text>();
|
||||||
// var vessel = new ObjectVessel<Button, TMPro.TMP_Text>(button, text);
|
var vessel = new ObjectVessel<Selectable, TMPro.TMP_Text>(selectable, text);
|
||||||
// return vessel;
|
return vessel;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
protected virtual void ListenPageSelectable(ObjectVessel<Selectable, TMPro.TMP_Text> selectableVessel, Action<int> selectPageAction)
|
||||||
/// 释放页面索引按钮
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void ReleasePageIndexButton(Component comp)
|
|
||||||
{
|
{
|
||||||
pageButtonPool.IndirectRelease(comp);
|
if (selectableVessel.Target0 is Button button)
|
||||||
|
{
|
||||||
|
button.onClick.AddListener(() =>
|
||||||
|
{
|
||||||
|
selectPageAction?.Invoke(currentPageIndex);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,19 +10,14 @@ using XericUI.Core.Vessel;
|
|||||||
|
|
||||||
namespace XericUI.FlipPage
|
namespace XericUI.FlipPage
|
||||||
{
|
{
|
||||||
public delegate void PageIndexAction(int pageIndex, int pageOffset, int totalPageCount);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 翻页管理器
|
/// 翻页管理器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <code>
|
||||||
|
/// 翻页允许按页,按项目进行管理。
|
||||||
|
/// </code>
|
||||||
public class XericFlipPageIndexVesselBase : XericUIBehaciour
|
public class XericFlipPageIndexVesselBase : XericUIBehaciour
|
||||||
{
|
{
|
||||||
#region 委托事件
|
|
||||||
|
|
||||||
public event PageIndexAction OnPageFlip;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 设定参数
|
#region 设定参数
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -32,30 +27,123 @@ namespace XericUI.FlipPage
|
|||||||
[LabelText("候选页数量")]
|
[LabelText("候选页数量")]
|
||||||
[BoxGroup("设定", centerLabel: true)]
|
[BoxGroup("设定", centerLabel: true)]
|
||||||
#endif
|
#endif
|
||||||
|
[Tooltip("最大同时呈现的页面选择器数量")]
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private int candidatesNumber = 1;
|
protected float candidatesNumber = 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 翻页可以跨越索引边接(循环索引)
|
/// 翻页可以跨越索引边接(循环索引)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#if ODIN_INSPECTOR
|
#if ODIN_INSPECTOR
|
||||||
[LabelText("翻页时允许跨越索引循环")]
|
[LabelText("翻页时允许跨越索引循环")]
|
||||||
[BoxGroup("设定", centerLabel: true)]
|
[BoxGroup("设定")]
|
||||||
#endif
|
#endif
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private bool canPassIndexBoundary;
|
protected bool canPassIndexBoundary;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面默认最大项目数量
|
||||||
|
/// </summary>
|
||||||
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("单个页面内默认最多项目数量")]
|
||||||
|
[BoxGroup("设定")]
|
||||||
|
#endif
|
||||||
|
[SerializeField]
|
||||||
|
protected int defaultItemCountPerPage = -1;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 类内类型
|
#region 类内类型
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面信息
|
||||||
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class PageInfo
|
public abstract class PageInfo
|
||||||
{
|
{
|
||||||
|
#region 字段属性
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面名称
|
||||||
|
/// </summary>
|
||||||
#if ODIN_INSPECTOR
|
#if ODIN_INSPECTOR
|
||||||
[LabelText("页面名称")]
|
[LabelText("页面名称")]
|
||||||
#endif
|
#endif
|
||||||
public string Name = DateTime.Now.Ticks.ToString();
|
public string name = DateTime.Now.Ticks.ToString();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面内项目列表
|
||||||
|
/// </summary>
|
||||||
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("页面项目信息")]
|
||||||
|
#endif
|
||||||
|
public List<ItemInfo> itemInfos = new List<ItemInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从零开始计数的页面下标
|
||||||
|
/// </summary>
|
||||||
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("页面索引[0, n]")]
|
||||||
|
#endif
|
||||||
|
public int pageNumber { get; internal set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 生命周期
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面显示时
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quickVisit">快速浏览(用于区分动画和逻辑,为真时,不应当在动画事件后继续加载数据)</param>
|
||||||
|
protected internal abstract void OnPageVisible(bool quickVisit);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页面隐藏时
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="quickVisit">快速浏览(用于区分动画和逻辑,为真时,不应当在动画事件后继续加载数据)</param>
|
||||||
|
protected internal abstract void OnPageInvisible(bool quickVisit);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"[{nameof(PageInfo)}] ({name})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 项目信息
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public abstract class ItemInfo
|
||||||
|
{
|
||||||
|
#region 字段属性
|
||||||
|
|
||||||
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("项目名称")]
|
||||||
|
#endif
|
||||||
|
public string name = DateTime.Now.Ticks.ToString();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 生命周期
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当项目显示时
|
||||||
|
/// </summary>
|
||||||
|
protected internal abstract void OnItemVisible();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当项目隐藏时
|
||||||
|
/// </summary>
|
||||||
|
protected internal abstract void OnItemInvisible();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"[{nameof(ItemInfo)}] ({name})";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -63,19 +151,40 @@ namespace XericUI.FlipPage
|
|||||||
#region 字段属性
|
#region 字段属性
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前页面
|
/// 当前选中的页面索引
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private int _currentPageIndex = 0;
|
#if ODIN_INSPECTOR
|
||||||
|
[LabelText("当前选中页面索引")]
|
||||||
|
#endif
|
||||||
|
[SerializeField]
|
||||||
|
protected int currentPageIndex = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 所有页面
|
/// 所有页面
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private LinkedList<PageInfo> _pageInfos = new LinkedList<PageInfo>();
|
private LinkedList<PageInfo> _pageInfos = new LinkedList<PageInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所有列表项目
|
||||||
|
/// </summary>
|
||||||
|
private HashSet<ItemInfo> _itemInfos = new HashSet<ItemInfo>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前选中页面节点
|
||||||
|
/// </summary>
|
||||||
|
public LinkedListNode<PageInfo> currentPageNode = null;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所有页面
|
||||||
|
/// </summary>
|
||||||
public LinkedList<PageInfo> PageInfos => _pageInfos;
|
public LinkedList<PageInfo> PageInfos => _pageInfos;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前选中页面内容
|
||||||
|
/// </summary>
|
||||||
|
public PageInfo currentPage => currentPageNode.Value;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 生命周期
|
#region 生命周期
|
||||||
@@ -88,17 +197,40 @@ namespace XericUI.FlipPage
|
|||||||
protected override void Start()
|
protected override void Start()
|
||||||
{
|
{
|
||||||
base.Start();
|
base.Start();
|
||||||
FlipPage(_currentPageIndex);
|
|
||||||
|
FlipPage(currentPageIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 翻页管理
|
#region 翻页管理
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当发生翻页时(这会在整个翻页动作流程的最后执行)
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnFlipPage()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过指令筛选页面
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pageNumber"></param>
|
||||||
|
/// <param name="forceRefresh"></param>
|
||||||
|
public virtual void FlipPage(string pageNumber, bool forceRefresh = false)
|
||||||
|
{
|
||||||
|
if (float.TryParse(pageNumber, out var index))
|
||||||
|
{
|
||||||
|
FlipPage((int)index, forceRefresh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 翻到指定页
|
/// 翻到指定页
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pageIndex"></param>
|
/// <param name="pageIndex"></param>
|
||||||
|
/// <param name="quickSwitchPage">快速翻页,</param>
|
||||||
/// <param name="forceRefresh"></param>
|
/// <param name="forceRefresh"></param>
|
||||||
public virtual void FlipPage(int pageIndex, bool forceRefresh = false)
|
public virtual void FlipPage(int pageIndex, bool forceRefresh = false)
|
||||||
{
|
{
|
||||||
@@ -109,20 +241,54 @@ namespace XericUI.FlipPage
|
|||||||
else
|
else
|
||||||
pageIndex = MacroMath.PMod(pageIndex, _pageInfos.Count - 1);
|
pageIndex = MacroMath.PMod(pageIndex, _pageInfos.Count - 1);
|
||||||
// 检查翻页数量有效
|
// 检查翻页数量有效
|
||||||
if (!forceRefresh && _currentPageIndex == pageIndex)
|
if (!forceRefresh && currentPageIndex == pageIndex)
|
||||||
return;
|
return;
|
||||||
// 翻页计算
|
// 翻页计算
|
||||||
var pageIndexOffset = _currentPageIndex - pageIndex;
|
var pageIndexOffset = pageIndex - currentPageIndex;
|
||||||
var lastPageIndex = _currentPageIndex;
|
var lastPageIndex = currentPageIndex;
|
||||||
_currentPageIndex = pageIndex;
|
// 如果节点不存在,通过索引寻找
|
||||||
try
|
if (currentPageNode == null)
|
||||||
|
currentPageNode = _pageInfos.GetOrderNode().LandedIndex(currentPageIndex);
|
||||||
|
// 如果索引偏移,逐个移动
|
||||||
|
else if (pageIndexOffset > 0)
|
||||||
{
|
{
|
||||||
// 翻页事件委托
|
for (var i = 0; i < pageIndexOffset; i++)
|
||||||
OnPageFlip?.Invoke(pageIndex, pageIndexOffset, _pageInfos.Count);
|
{
|
||||||
|
var next = currentPageNode!.Next;
|
||||||
|
SwitchPage(next, _pageInfos.Last, i + 1 == pageIndexOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
else if (pageIndexOffset < 0)
|
||||||
{
|
{
|
||||||
Debug.LogError($"翻页时委托错误已捕获\n{e.Message}\n{e.Data}");
|
for (var i = 0; i > pageIndexOffset; i--)
|
||||||
|
{
|
||||||
|
var previa = currentPageNode!.Previous;
|
||||||
|
SwitchPage(previa, _pageInfos.First, i - 1 == pageIndexOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 没有翻动有效页,退出
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
currentPageIndex = pageIndex;
|
||||||
|
OnFlipPage();
|
||||||
|
|
||||||
|
// 翻页
|
||||||
|
void SwitchPage(LinkedListNode<PageInfo> newPageNode, LinkedListNode<PageInfo> defualtPageNode, bool quickPage)
|
||||||
|
{
|
||||||
|
if (newPageNode != null)
|
||||||
|
{
|
||||||
|
currentPage.OnPageInvisible(quickPage);
|
||||||
|
currentPageNode = newPageNode;
|
||||||
|
currentPage.OnPageVisible(quickPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canPassIndexBoundary)
|
||||||
|
{
|
||||||
|
currentPage.OnPageInvisible(quickPage);
|
||||||
|
currentPageNode = defualtPageNode;
|
||||||
|
currentPage.OnPageVisible(quickPage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +308,7 @@ namespace XericUI.FlipPage
|
|||||||
[HorizontalGroup("翻页"), Button("翻到上一页")]
|
[HorizontalGroup("翻页"), Button("翻到上一页")]
|
||||||
#endif
|
#endif
|
||||||
public void FlipPageToPrevious()
|
public void FlipPageToPrevious()
|
||||||
=> FlipPage(_currentPageIndex - 1);
|
=> FlipPage(currentPageIndex - 1);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 翻到下一页
|
/// 翻到下一页
|
||||||
@@ -151,7 +317,7 @@ namespace XericUI.FlipPage
|
|||||||
[HorizontalGroup("翻页"), Button("翻到下一页")]
|
[HorizontalGroup("翻页"), Button("翻到下一页")]
|
||||||
#endif
|
#endif
|
||||||
public void FlipPageToNext()
|
public void FlipPageToNext()
|
||||||
=> FlipPage(_currentPageIndex + 1);
|
=> FlipPage(currentPageIndex + 1);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 翻到结尾
|
/// 翻到结尾
|
||||||
@@ -162,58 +328,111 @@ namespace XericUI.FlipPage
|
|||||||
public void FlipPageToEnd()
|
public void FlipPageToEnd()
|
||||||
=> FlipPage(_pageInfos.Count - 1);
|
=> FlipPage(_pageInfos.Count - 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加页面
|
/// 添加页面在开头
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void AddPage(PageInfo pageInfo)
|
public virtual void AddPageFirst(PageInfo pageInfo)
|
||||||
{
|
{
|
||||||
|
if (pageInfo == null)
|
||||||
|
{
|
||||||
|
Debug.LogError($"不能添加一个空的页面内容到管理器中!", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加页面
|
||||||
|
_pageInfos.AddFirst(pageInfo);
|
||||||
|
// 添加页面下标
|
||||||
|
pageInfo.pageNumber = 0;
|
||||||
|
// 更新后面页面的索引
|
||||||
|
RefreshAllPageNumber();
|
||||||
|
// 刷新页面
|
||||||
|
FlipPage(currentPageIndex, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加页面在结尾
|
||||||
|
/// </summary>
|
||||||
|
public virtual void AddPageLast(PageInfo pageInfo)
|
||||||
|
{
|
||||||
|
if (pageInfo == null)
|
||||||
|
{
|
||||||
|
Debug.LogError($"不能添加一个空的页面内容到管理器中!", this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 添加页面下标
|
||||||
|
pageInfo.pageNumber = _pageInfos.Count;
|
||||||
|
// 添加页面
|
||||||
_pageInfos.AddLast(pageInfo);
|
_pageInfos.AddLast(pageInfo);
|
||||||
// 刷新页面
|
// 刷新页面
|
||||||
FlipPage(_currentPageIndex, true);
|
FlipPage(currentPageIndex, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除页面
|
/// 移除页面
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RemovePage(int pageIndex)
|
public virtual void RemovePage(int pageIndex)
|
||||||
{
|
{
|
||||||
RemovePage(IndexOfPage(pageIndex));
|
if (0 > pageIndex || pageIndex > _pageInfos.Count)
|
||||||
}
|
{
|
||||||
|
Debug.LogError($"不能移除不在范围内的索引{pageIndex}!", this);
|
||||||
/// <summary>
|
return;
|
||||||
/// 移除页面
|
}
|
||||||
/// </summary>
|
// 获取页面节点
|
||||||
/// <param name="pageRef"></param>
|
var page = _pageInfos.GetOrderNode().LandedIndex(pageIndex);
|
||||||
public void RemovePage(PageInfo pageRef)
|
// 更新后面页面的索引
|
||||||
{
|
var tempPage = page;
|
||||||
_pageInfos.Remove(pageRef);
|
var tempPageNumber = page.Value.pageNumber;
|
||||||
|
while (tempPage.Next != null)
|
||||||
|
{
|
||||||
|
tempPage = tempPage.Next;
|
||||||
|
tempPage.Value.pageNumber = tempPageNumber++;
|
||||||
|
}
|
||||||
|
// 如果移除的是当前页面,执行关闭操作
|
||||||
|
if (currentPageNode == page)
|
||||||
|
{
|
||||||
|
page.Value.OnPageInvisible(true);
|
||||||
|
currentPageNode = null;
|
||||||
|
}
|
||||||
|
_pageInfos.Remove(page);
|
||||||
// 刷新页面
|
// 刷新页面
|
||||||
FlipPage(_currentPageIndex, true);
|
FlipPage(currentPageIndex, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清除所有页面
|
||||||
|
/// </summary>
|
||||||
|
public virtual void CleanPage()
|
||||||
|
{
|
||||||
|
_pageInfos.Clear();
|
||||||
|
currentPageNode = null;
|
||||||
|
currentPageIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 交换AB页面
|
/// 交换AB页面
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SwapPages(int pageIndexA, int pageIndexB)
|
public virtual void SwapPages(int pageIndexA, int pageIndexB)
|
||||||
{
|
{
|
||||||
var a = _pageInfos.GetOrderNode().LandedIndex(pageIndexA);
|
var a = _pageInfos.GetOrderNode().LandedIndex(pageIndexA);
|
||||||
var b = _pageInfos.GetOrderNode().LandedIndex(pageIndexB);
|
var b = _pageInfos.GetOrderNode().LandedIndex(pageIndexB);
|
||||||
|
// 交换节点
|
||||||
_pageInfos.SwapNodes(a, b);
|
_pageInfos.SwapNodes(a, b);
|
||||||
|
// 交换页面索引
|
||||||
|
(a.Value.pageNumber, b.Value.pageNumber) = (b.Value.pageNumber, a.Value.pageNumber);
|
||||||
// 刷新页面
|
// 刷新页面
|
||||||
FlipPage(_currentPageIndex, true);
|
FlipPage(currentPageIndex, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 选择索引下的页面
|
/// 刷新所有页面索引
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pageIndex"></param>
|
public void RefreshAllPageNumber()
|
||||||
/// <returns></returns>
|
|
||||||
public PageInfo IndexOfPage(int pageIndex)
|
|
||||||
{
|
{
|
||||||
return _pageInfos.LandedIndex(pageIndex);
|
var index = 0;
|
||||||
|
foreach (var page in _pageInfos)
|
||||||
|
{
|
||||||
|
page.pageNumber = index++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
Reference in New Issue
Block a user