diff --git a/Runtime/RecyclerView/Adapter/Adapter.cs b/Runtime/RecyclerView/Adapter/Adapter.cs
index e9ed5d8..71aad78 100644
--- a/Runtime/RecyclerView/Adapter/Adapter.cs
+++ b/Runtime/RecyclerView/Adapter/Adapter.cs
@@ -3,6 +3,10 @@ using System.Collections.Generic;
namespace AlicizaX.UI
{
+ ///
+ /// RecyclerView 的通用适配器,支持数据绑定、选中状态和列表操作
+ ///
+ /// 数据类型,必须实现 ISimpleViewData 接口
public class Adapter : IAdapter where T : ISimpleViewData
{
protected RecyclerView recyclerView;
@@ -12,20 +16,38 @@ namespace AlicizaX.UI
protected int choiceIndex = -1;
+ ///
+ /// 当前选中项的索引
+ ///
public int ChoiceIndex
{
get => choiceIndex;
set { SetChoiceIndex(value); }
}
+ ///
+ /// 构造函数
+ ///
+ /// RecyclerView 实例
public Adapter(RecyclerView recyclerView) : this(recyclerView, new List(), null)
{
}
+ ///
+ /// 构造函数
+ ///
+ /// RecyclerView 实例
+ /// 数据列表
public Adapter(RecyclerView recyclerView, List list) : this(recyclerView, list, null)
{
}
+ ///
+ /// 构造函数
+ ///
+ /// RecyclerView 实例
+ /// 数据列表
+ /// 列表项点击回调
public Adapter(RecyclerView recyclerView, List list, Action onItemClick)
{
this.recyclerView = recyclerView;
@@ -33,21 +55,33 @@ namespace AlicizaX.UI
this.onItemClick = onItemClick;
}
+ ///
+ /// 获取列表项总数
+ ///
public virtual int GetItemCount()
{
return list == null ? 0 : list.Count;
}
+ ///
+ /// 获取实际数据项数量
+ ///
public virtual int GetRealCount()
{
return GetItemCount();
}
+ ///
+ /// 获取指定索引位置的视图名称
+ ///
public virtual string GetViewName(int index)
{
return "";
}
+ ///
+ /// 绑定视图持有者与数据
+ ///
public virtual void OnBindViewHolder(ViewHolder viewHolder, int index)
{
if (index < 0 || index >= GetItemCount()) return;
@@ -63,12 +97,19 @@ namespace AlicizaX.UI
viewHolder.BindChoiceState(index == choiceIndex);
}
+ ///
+ /// 通知数据已更改
+ ///
public virtual void NotifyDataChanged()
{
recyclerView.RequestLayout();
recyclerView.Refresh();
}
+ ///
+ /// 设置数据列表并刷新视图
+ ///
+ /// 新的数据列表
public virtual void SetList(List list)
{
this.list = list;
@@ -76,6 +117,11 @@ namespace AlicizaX.UI
NotifyDataChanged();
}
+ ///
+ /// 获取指定索引的数据
+ ///
+ /// 数据索引
+ /// 数据对象,索引无效时返回 default
public T GetData(int index)
{
if (index < 0 || index >= GetItemCount()) return default;
@@ -83,36 +129,62 @@ namespace AlicizaX.UI
return list[index];
}
+ ///
+ /// 添加单个数据项
+ ///
+ /// 要添加的数据项
public void Add(T item)
{
list.Add(item);
NotifyDataChanged();
}
+ ///
+ /// 批量添加数据项
+ ///
+ /// 要添加的数据集合
public void AddRange(IEnumerable collection)
{
list.AddRange(collection);
NotifyDataChanged();
}
+ ///
+ /// 在指定位置插入数据项
+ ///
+ /// 插入位置
+ /// 要插入的数据项
public void Insert(int index, T item)
{
list.Insert(index, item);
NotifyDataChanged();
}
+ ///
+ /// 在指定位置批量插入数据项
+ ///
+ /// 插入位置
+ /// 要插入的数据集合
public void InsertRange(int index, IEnumerable collection)
{
list.InsertRange(index, collection);
NotifyDataChanged();
}
+ ///
+ /// 移除指定的数据项
+ ///
+ /// 要移除的数据项
public void Remove(T item)
{
int index = list.IndexOf(item);
RemoveAt(index);
}
+ ///
+ /// 移除指定索引位置的数据项
+ ///
+ /// 要移除的索引
public void RemoveAt(int index)
{
if (index < 0 || index >= GetItemCount()) return;
@@ -121,47 +193,79 @@ namespace AlicizaX.UI
NotifyDataChanged();
}
+ ///
+ /// 移除指定范围的数据项
+ ///
+ /// 起始索引
+ /// 移除数量
public void RemoveRange(int index, int count)
{
list.RemoveRange(index, count);
NotifyDataChanged();
}
+ ///
+ /// 移除所有符合条件的数据项
+ ///
+ /// 匹配条件
public void RemoveAll(Predicate match)
{
list.RemoveAll(match);
NotifyDataChanged();
}
+ ///
+ /// 清空所有数据
+ ///
public void Clear()
{
list.Clear();
NotifyDataChanged();
}
+ ///
+ /// 反转指定范围的数据项顺序
+ ///
+ /// 起始索引
+ /// 反转数量
public void Reverse(int index, int count)
{
list.Reverse(index, count);
NotifyDataChanged();
}
+ ///
+ /// 反转所有数据项顺序
+ ///
public void Reverse()
{
list.Reverse();
NotifyDataChanged();
}
+ ///
+ /// 使用指定的比较器排序数据
+ ///
+ /// 比较器
public void Sort(Comparison comparison)
{
list.Sort(comparison);
NotifyDataChanged();
}
+ ///
+ /// 设置列表项点击回调
+ ///
+ /// 点击回调
public void SetOnItemClick(Action onItemClick)
{
this.onItemClick = onItemClick;
}
+ ///
+ /// 设置选中项索引
+ ///
+ /// 要选中的索引
protected void SetChoiceIndex(int index)
{
if (index == choiceIndex) return;
@@ -185,6 +289,12 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 尝试获取指定索引的视图持有者
+ ///
+ /// 数据索引
+ /// 输出的视图持有者
+ /// 是否成功获取
private bool TryGetViewHolder(int index, out ViewHolder viewHolder)
{
viewHolder = recyclerView.ViewProvider.GetViewHolder(index);
diff --git a/Runtime/RecyclerView/Adapter/IAdapter.cs b/Runtime/RecyclerView/Adapter/IAdapter.cs
index d2b9d06..dcfcb88 100644
--- a/Runtime/RecyclerView/Adapter/IAdapter.cs
+++ b/Runtime/RecyclerView/Adapter/IAdapter.cs
@@ -1,15 +1,39 @@
namespace AlicizaX.UI
{
+ ///
+ /// RecyclerView 适配器接口,负责提供数据和绑定视图
+ ///
public interface IAdapter
{
+ ///
+ /// 获取列表项总数(包括循环或分组后的虚拟数量)
+ ///
+ /// 列表项总数
int GetItemCount();
+ ///
+ /// 获取实际数据项数量(不包括循环或分组的虚拟数量)
+ ///
+ /// 实际数据项数量
int GetRealCount();
+ ///
+ /// 获取指定索引位置的视图名称,用于视图类型区分
+ ///
+ /// 列表项索引
+ /// 视图名称
string GetViewName(int index);
+ ///
+ /// 绑定视图持有者与数据
+ ///
+ /// 视图持有者
+ /// 数据索引
void OnBindViewHolder(ViewHolder viewHolder, int index);
+ ///
+ /// 通知数据已更改,触发视图刷新
+ ///
void NotifyDataChanged();
}
}
diff --git a/Runtime/RecyclerView/EaseUtil.cs b/Runtime/RecyclerView/EaseUtil.cs
index 7ac6fe0..46ea76e 100644
--- a/Runtime/RecyclerView/EaseUtil.cs
+++ b/Runtime/RecyclerView/EaseUtil.cs
@@ -1,12 +1,23 @@
using System;
+///
+/// 缓动函数工具类
+/// 提供各种常用的缓动函数,用于实现平滑的动画效果
+/// 基于 https://easings.net/ 的标准缓动函数
+///
public class EaseUtil
{
+ ///
+ /// 正弦缓入函数
+ ///
public static double EaseInSine(float x)
{
return 1 - Math.Cos(x * Math.PI / 2);
}
+ ///
+ /// 正弦缓出函数
+ ///
public static double EaseOutSine(float x)
{
return Math.Sin(x * Math.PI / 2);
diff --git a/Runtime/RecyclerView/Layout/LayoutManager.cs b/Runtime/RecyclerView/Layout/LayoutManager.cs
index 2b34e39..e64d8ed 100644
--- a/Runtime/RecyclerView/Layout/LayoutManager.cs
+++ b/Runtime/RecyclerView/Layout/LayoutManager.cs
@@ -2,10 +2,18 @@ using UnityEngine;
namespace AlicizaX.UI
{
+ ///
+ /// 布局管理器抽象基类
+ /// 负责计算和管理 RecyclerView 中列表项的位置、大小和可见性
+ /// 子类需要实现具体的布局算法(如线性、网格、圆形等)
+ ///
[System.Serializable]
public abstract class LayoutManager : ILayoutManager
{
protected Vector2 viewportSize;
+ ///
+ /// 获取视口大小(可见区域的尺寸)
+ ///
public Vector2 ViewportSize
{
get => viewportSize;
@@ -13,6 +21,9 @@ namespace AlicizaX.UI
}
protected Vector2 contentSize;
+ ///
+ /// 获取内容总大小(所有列表项占据的总尺寸)
+ ///
public Vector2 ContentSize
{
get => contentSize;
@@ -20,6 +31,9 @@ namespace AlicizaX.UI
}
protected Vector2 contentOffset;
+ ///
+ /// 获取内容偏移量(用于对齐计算)
+ ///
public Vector2 ContentOffset
{
get => contentOffset;
@@ -27,6 +41,9 @@ namespace AlicizaX.UI
}
protected Vector2 viewportOffset;
+ ///
+ /// 获取视口偏移量(用于对齐计算)
+ ///
public Vector2 ViewportOffset
{
get => viewportOffset;
@@ -34,6 +51,9 @@ namespace AlicizaX.UI
}
protected IAdapter adapter;
+ ///
+ /// 获取或设置数据适配器
+ ///
public IAdapter Adapter
{
get => adapter;
@@ -41,6 +61,9 @@ namespace AlicizaX.UI
}
protected ViewProvider viewProvider;
+ ///
+ /// 获取或设置视图提供器
+ ///
public ViewProvider ViewProvider
{
get => viewProvider;
@@ -48,6 +71,9 @@ namespace AlicizaX.UI
}
protected RecyclerView recyclerView;
+ ///
+ /// 获取或设置关联的 RecyclerView 实例
+ ///
public virtual RecyclerView RecyclerView
{
get => recyclerView;
@@ -55,6 +81,9 @@ namespace AlicizaX.UI
}
protected Direction direction;
+ ///
+ /// 获取或设置滚动方向
+ ///
public Direction Direction
{
get => direction;
@@ -62,6 +91,9 @@ namespace AlicizaX.UI
}
protected Alignment alignment;
+ ///
+ /// 获取或设置对齐方式
+ ///
public Alignment Alignment
{
get => alignment;
@@ -69,6 +101,9 @@ namespace AlicizaX.UI
}
protected Vector2 spacing;
+ ///
+ /// 获取或设置列表项间距
+ ///
public Vector2 Spacing
{
get => spacing;
@@ -76,6 +111,9 @@ namespace AlicizaX.UI
}
protected Vector2 padding;
+ ///
+ /// 获取或设置内边距
+ ///
public Vector2 Padding
{
get => padding;
@@ -83,6 +121,9 @@ namespace AlicizaX.UI
}
protected int unit = 1;
+ ///
+ /// 获取或设置布局单元(用于网格布局等,表示一次处理多少个项)
+ ///
public int Unit
{
get => unit;
@@ -90,10 +131,17 @@ namespace AlicizaX.UI
}
+ ///
+ /// 获取当前滚动位置
+ ///
public float ScrollPosition => recyclerView.GetScrollPosition();
public LayoutManager() { }
+ ///
+ /// 设置内容大小
+ /// 计算视口大小、内容大小以及各种偏移量
+ ///
public void SetContentSize()
{
viewportSize = recyclerView.GetComponent().rect.size;
@@ -102,6 +150,10 @@ namespace AlicizaX.UI
viewportOffset = CalculateViewportOffset();
}
+ ///
+ /// 更新所有可见 ViewHolder 的布局
+ /// 遍历所有当前显示的 ViewHolder 并重新计算其位置
+ ///
public void UpdateLayout()
{
foreach (var viewHolder in viewProvider.ViewHolders)
@@ -110,6 +162,11 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 为指定的 ViewHolder 设置布局位置
+ ///
+ /// 要布局的 ViewHolder
+ /// ViewHolder 对应的数据索引
public virtual void Layout(ViewHolder viewHolder, int index)
{
Vector2 pos = CalculatePosition(index);
@@ -119,24 +176,67 @@ namespace AlicizaX.UI
viewHolder.RectTransform.anchoredPosition3D = position;
}
+ ///
+ /// 计算内容总大小(抽象方法,由子类实现)
+ ///
+ /// 内容的总尺寸
public abstract Vector2 CalculateContentSize();
+ ///
+ /// 计算指定索引的 ViewHolder 位置(抽象方法,由子类实现)
+ ///
+ /// 数据索引
+ /// ViewHolder 的位置
public abstract Vector2 CalculatePosition(int index);
+ ///
+ /// 计算内容偏移量(抽象方法,由子类实现)
+ ///
+ /// 内容偏移量
public abstract Vector2 CalculateContentOffset();
+ ///
+ /// 计算视口偏移量(抽象方法,由子类实现)
+ ///
+ /// 视口偏移量
public abstract Vector2 CalculateViewportOffset();
+ ///
+ /// 获取当前可见区域的起始索引(抽象方法,由子类实现)
+ ///
+ /// 起始索引
public abstract int GetStartIndex();
+ ///
+ /// 获取当前可见区域的结束索引(抽象方法,由子类实现)
+ ///
+ /// 结束索引
public abstract int GetEndIndex();
+ ///
+ /// 将数据索引转换为滚动位置(抽象方法,由子类实现)
+ ///
+ /// 数据索引
+ /// 对应的滚动位置
public abstract float IndexToPosition(int index);
+ ///
+ /// 将滚动位置转换为数据索引(抽象方法,由子类实现)
+ ///
+ /// 滚动位置
+ /// 对应的数据索引
public abstract int PositionToIndex(float position);
+ ///
+ /// 执行列表项动画(虚方法,子类可选择性重写)
+ ///
public virtual void DoItemAnimation() { }
+ ///
+ /// 判断起始位置的 ViewHolder 是否完全可见
+ ///
+ /// 数据索引
+ /// 如果完全可见返回 true,否则返回 false
public virtual bool IsFullVisibleStart(int index)
{
Vector2 vector2 = CalculatePosition(index);
@@ -144,6 +244,11 @@ namespace AlicizaX.UI
return position + GetOffset() >= 0;
}
+ ///
+ /// 判断起始位置的 ViewHolder 是否完全不可见
+ ///
+ /// 数据索引
+ /// 如果完全不可见返回 true,否则返回 false
public virtual bool IsFullInvisibleStart(int index)
{
Vector2 vector2 = CalculatePosition(index + unit);
@@ -151,6 +256,11 @@ namespace AlicizaX.UI
return position + GetOffset() < 0;
}
+ ///
+ /// 判断结束位置的 ViewHolder 是否完全可见
+ ///
+ /// 数据索引
+ /// 如果完全可见返回 true,否则返回 false
public virtual bool IsFullVisibleEnd(int index)
{
Vector2 vector2 = CalculatePosition(index + unit);
@@ -159,6 +269,11 @@ namespace AlicizaX.UI
return position + GetOffset() <= viewLength;
}
+ ///
+ /// 判断结束位置的 ViewHolder 是否完全不可见
+ ///
+ /// 数据索引
+ /// 如果完全不可见返回 true,否则返回 false
public virtual bool IsFullInvisibleEnd(int index)
{
Vector2 vector2 = CalculatePosition(index);
@@ -167,6 +282,11 @@ namespace AlicizaX.UI
return position + GetOffset() > viewLength;
}
+ ///
+ /// 判断指定索引的 ViewHolder 是否可见(部分或完全)
+ ///
+ /// 数据索引
+ /// 如果可见返回 true,否则返回 false
public virtual bool IsVisible(int index)
{
float position, viewLength;
@@ -189,6 +309,11 @@ namespace AlicizaX.UI
return false;
}
+ ///
+ /// 获取适配内容大小
+ /// 根据对齐方式计算实际显示的内容长度
+ ///
+ /// 适配后的内容大小
protected virtual float GetFitContentSize()
{
float len;
@@ -203,23 +328,40 @@ namespace AlicizaX.UI
return len;
}
+ ///
+ /// 获取偏移量
+ /// 计算内容偏移和视口偏移的组合值
+ ///
+ /// 总偏移量
protected virtual float GetOffset()
{
return direction == Direction.Vertical ? -contentOffset.y + viewportOffset.y : -contentOffset.x + viewportOffset.x;
}
}
+ ///
+ /// 滚动方向枚举
+ ///
public enum Direction
{
+ /// 垂直滚动
Vertical = 0,
+ /// 水平滚动
Horizontal = 1,
+ /// 自定义滚动
Custom = 2
}
+ ///
+ /// 对齐方式枚举
+ ///
public enum Alignment
{
+ /// 左对齐
Left,
+ /// 居中对齐
Center,
+ /// 顶部对齐
Top
}
}
diff --git a/Runtime/RecyclerView/RecyclerView.cs b/Runtime/RecyclerView/RecyclerView.cs
index 940d4d1..4184220 100644
--- a/Runtime/RecyclerView/RecyclerView.cs
+++ b/Runtime/RecyclerView/RecyclerView.cs
@@ -4,6 +4,11 @@ using UnityEngine.UI;
namespace AlicizaX.UI
{
+ ///
+ /// RecyclerView 核心组件,用于高效显示大量列表数据
+ /// 通过视图回收和复用机制,只渲染可见区域的项目,大幅提升性能
+ /// 支持垂直/水平滚动、网格布局、循环滚动等多种布局模式
+ ///
public class RecyclerView : MonoBehaviour
{
#region Serialized Fields - Layout Settings
@@ -57,24 +62,36 @@ namespace AlicizaX.UI
#region Public Properties - Layout Settings
+ ///
+ /// 获取或设置列表的滚动方向(垂直、水平或自定义)
+ ///
public Direction Direction
{
get => direction;
set => direction = value;
}
+ ///
+ /// 获取或设置列表项的对齐方式(起始、居中或结束)
+ ///
public Alignment Alignment
{
get => alignment;
set => alignment = value;
}
+ ///
+ /// 获取或设置列表项之间的间距(X轴和Y轴)
+ ///
public Vector2 Spacing
{
get => spacing;
set => spacing = value;
}
+ ///
+ /// 获取或设置列表内容的内边距(X轴和Y轴)
+ ///
public Vector2 Padding
{
get => padding;
@@ -85,6 +102,10 @@ namespace AlicizaX.UI
#region Public Properties - Scroll Settings
+ ///
+ /// 获取或设置是否启用滚动功能
+ /// 启用时会激活 Scroller 组件并显示滚动条(如果配置了)
+ ///
public bool Scroll
{
get => scroll;
@@ -116,6 +137,11 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 获取或设置是否启用吸附功能
+ /// 启用时滚动停止后会自动对齐到最近的列表项
+ /// 注意:此功能依赖于 Scroll 属性,只有在滚动启用时才生效
+ ///
public bool Snap
{
get => snap;
@@ -136,6 +162,10 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 获取或设置滚动速度(范围:1-50)
+ /// 值越大,滚动响应越快
+ ///
public float ScrollSpeed
{
get => scrollSpeed;
@@ -151,6 +181,10 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 获取或设置鼠标滚轮的滚动速度(范围:10-50)
+ /// 值越大,滚轮滚动的距离越大
+ ///
public float WheelSpeed
{
get => wheelSpeed;
@@ -171,12 +205,20 @@ namespace AlicizaX.UI
#region Public Properties - Components
+ ///
+ /// 获取或设置 ViewHolder 模板数组
+ /// 用于创建和复用列表项视图
+ ///
public ViewHolder[] Templates
{
get => templates;
set => templates = value;
}
+ ///
+ /// 获取内容容器的 RectTransform
+ /// 所有列表项都会作为此容器的子对象
+ ///
public RectTransform Content
{
get
@@ -190,10 +232,21 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 获取滚动条组件
+ ///
public Scrollbar Scrollbar => scrollbar;
+ ///
+ /// 获取滚动控制器组件
+ ///
public Scroller Scroller => scroller;
+ ///
+ /// 获取视图提供器
+ /// 负责创建、回收和管理 ViewHolder 实例
+ /// 根据模板数量自动选择 SimpleViewProvider 或 MixedViewProvider
+ ///
public ViewProvider ViewProvider
{
get
@@ -213,8 +266,15 @@ namespace AlicizaX.UI
#region Public Properties - State
+ ///
+ /// 获取或设置当前绑定的适配器
+ /// 适配器负责提供数据和创建 ViewHolder
+ ///
public IAdapter RecyclerViewAdapter { get; set; }
+ ///
+ /// 获取或设置当前显示的列表项索引
+ ///
public int CurrentIndex
{
get => currentIndex;
@@ -225,7 +285,15 @@ namespace AlicizaX.UI
#region Events
+ ///
+ /// 当前索引改变时触发的事件
+ /// 参数为新的索引值
+ ///
public Action OnIndexChanged;
+
+ ///
+ /// 滚动位置改变时触发的事件
+ ///
public Action OnScrollValueChanged;
#endregion
@@ -287,6 +355,10 @@ namespace AlicizaX.UI
#region Public Methods - Setup
+ ///
+ /// 设置数据适配器并初始化布局管理器
+ ///
+ /// 要绑定的适配器实例
public void SetAdapter(IAdapter adapter)
{
if (adapter == null)
@@ -308,6 +380,10 @@ namespace AlicizaX.UI
layoutManager.Padding = padding;
}
+ ///
+ /// 重置列表状态
+ /// 清空所有 ViewHolder 并将滚动位置重置为起始位置
+ ///
public void Reset()
{
viewProvider?.Reset();
@@ -327,6 +403,10 @@ namespace AlicizaX.UI
#region Public Methods - Layout
+ ///
+ /// 刷新列表显示
+ /// 清空当前所有 ViewHolder 并根据当前滚动位置重新创建可见项
+ ///
public void Refresh()
{
ViewProvider.Clear();
@@ -342,6 +422,10 @@ namespace AlicizaX.UI
layoutManager.DoItemAnimation();
}
+ ///
+ /// 请求重新布局
+ /// 重新计算内容大小、视口大小,并更新滚动条显示状态
+ ///
public void RequestLayout()
{
layoutManager.SetContentSize();
@@ -359,11 +443,20 @@ namespace AlicizaX.UI
#region Public Methods - Scrolling
+ ///
+ /// 获取当前的滚动位置
+ ///
+ /// 当前滚动位置值,如果没有 Scroller 则返回 0
public float GetScrollPosition()
{
return scroller != null ? scroller.Position : 0;
}
+ ///
+ /// 滚动到指定索引的列表项
+ ///
+ /// 目标列表项的索引
+ /// 是否使用平滑滚动动画
public void ScrollTo(int index, bool smooth = false)
{
if (!scroll || scroller == null) return;
@@ -378,6 +471,14 @@ namespace AlicizaX.UI
UpdateCurrentIndex(index);
}
+ ///
+ /// 滚动到指定索引的列表项,并使用指定的对齐方式
+ ///
+ /// 目标列表项的索引
+ /// 对齐方式(起始、居中或结束)
+ /// 额外的偏移量
+ /// 是否使用平滑滚动动画
+ /// 滚动动画持续时间(秒)
public void ScrollToWithAlignment(int index, ScrollAlignment alignment, float offset = 0f, bool smooth = false, float duration = 0.3f)
{
if (!scroll || scroller == null) return;
diff --git a/Runtime/RecyclerView/ScrollAlignment.cs b/Runtime/RecyclerView/ScrollAlignment.cs
index 0dc3bd3..a25fb96 100644
--- a/Runtime/RecyclerView/ScrollAlignment.cs
+++ b/Runtime/RecyclerView/ScrollAlignment.cs
@@ -1,22 +1,22 @@
namespace AlicizaX.UI
{
///
- /// Defines how an item should be aligned when scrolling to it
+ /// 定义滚动到列表项时的对齐方式
///
public enum ScrollAlignment
{
///
- /// Align item to the top/left of the viewport
+ /// 将列表项对齐到视口的顶部/左侧
///
Start,
///
- /// Align item to the center of the viewport
+ /// 将列表项对齐到视口的中心
///
Center,
///
- /// Align item to the bottom/right of the viewport
+ /// 将列表项对齐到视口的底部/右侧
///
End
}
diff --git a/Runtime/RecyclerView/Scroller/IScroller.cs b/Runtime/RecyclerView/Scroller/IScroller.cs
index fdbbd05..79cddf4 100644
--- a/Runtime/RecyclerView/Scroller/IScroller.cs
+++ b/Runtime/RecyclerView/Scroller/IScroller.cs
@@ -2,14 +2,37 @@ using UnityEngine.Events;
namespace AlicizaX.UI
{
+ ///
+ /// 滚动控制器接口
+ /// 定义滚动行为的基本契约
+ ///
public interface IScroller
{
+ ///
+ /// 获取或设置当前滚动位置
+ ///
float Position { get; set; }
+ ///
+ /// 滚动到指定位置
+ ///
+ /// 目标位置
+ /// 是否使用平滑滚动
void ScrollTo(float position, bool smooth = false);
}
+ ///
+ /// 滚动位置改变事件
+ ///
public class ScrollerEvent : UnityEvent { }
+
+ ///
+ /// 滚动停止事件
+ ///
public class MoveStopEvent : UnityEvent { }
+
+ ///
+ /// 拖拽状态改变事件
+ ///
public class DraggingEvent : UnityEvent { }
}
diff --git a/Runtime/RecyclerView/UGList.cs b/Runtime/RecyclerView/UGList.cs
index cec2fdb..a9da453 100644
--- a/Runtime/RecyclerView/UGList.cs
+++ b/Runtime/RecyclerView/UGList.cs
@@ -3,14 +3,29 @@ using System.Collections.Generic;
namespace AlicizaX.UI
{
+ ///
+ /// UGList 基类
+ /// 提供简化的列表操作接口,封装 RecyclerView 和 Adapter 的交互
+ ///
+ /// 数据类型
+ /// 适配器类型
public abstract class UGListBase where TAdapter : Adapter where TData : ISimpleViewData
{
protected readonly RecyclerView _recyclerView;
protected readonly TAdapter _adapter;
+ ///
+ /// 获取关联的 RecyclerView 实例
+ ///
public RecyclerView RecyclerView => _recyclerView;
+ ///
+ /// 构造函数
+ ///
+ /// RecyclerView 实例
+ /// 适配器实例
+ /// 列表项点击回调
public UGListBase(RecyclerView recyclerView, TAdapter adapter, Action onItemClick = null)
{
_recyclerView = recyclerView;
@@ -27,10 +42,17 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 获取适配器实例
+ ///
public TAdapter Adapter => _adapter;
private List _datas;
+ ///
+ /// 获取或设置数据列表
+ /// 设置时会自动更新适配器
+ ///
public List Data
{
get => _datas;
@@ -42,49 +64,106 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 通用列表类
+ /// 用于显示简单的单一类型数据列表
+ ///
+ /// 数据类型,必须实现 ISimpleViewData
public class UGList : UGListBase> where TData : ISimpleViewData
{
+ ///
+ /// 构造函数
+ ///
+ /// RecyclerView 实例
+ /// 列表项点击回调
public UGList(RecyclerView recyclerView, Action onItemClick = null)
: base(recyclerView, new Adapter(recyclerView), onItemClick)
{
}
}
+ ///
+ /// 分组列表类
+ /// 用于显示带有分组头的列表数据
+ ///
+ /// 数据类型,必须实现 IGroupViewData
public class UGGroupList : UGListBase> where TData : class, IGroupViewData, new()
{
+ ///
+ /// 构造函数
+ ///
+ /// RecyclerView 实例
+ /// 分组头视图名称
+ /// 列表项点击回调
public UGGroupList(RecyclerView recyclerView, string groupViewName, Action onItemClick = null)
: base(recyclerView, new GroupAdapter(recyclerView, groupViewName), onItemClick)
{
}
}
+ ///
+ /// 循环列表类
+ /// 用于实现无限循环滚动的列表
+ ///
+ /// 数据类型,必须实现 ISimpleViewData
public class UGLoopList : UGListBase> where TData : ISimpleViewData, new()
{
+ ///
+ /// 构造函数
+ ///
+ /// RecyclerView 实例
+ /// 列表项点击回调
public UGLoopList(RecyclerView recyclerView, Action onItemClick = null)
: base(recyclerView, new LoopAdapter(recyclerView), onItemClick)
{
}
}
+ ///
+ /// 混合列表类
+ /// 用于显示多种不同类型的列表项
+ ///
+ /// 数据类型,必须实现 IMixedViewData
public class UGMixedList : UGListBase> where TData : IMixedViewData
{
+ ///
+ /// 构造函数
+ ///
+ /// RecyclerView 实例
+ /// 列表项点击回调
public UGMixedList(RecyclerView recyclerView, Action onItemClick = null)
: base(recyclerView, new MixedAdapter(recyclerView), onItemClick)
{
}
}
+ ///
+ /// UGList 创建辅助类
+ /// 提供便捷的静态方法来创建各种类型的列表
+ ///
public static class UGListCreateHelper
{
+ ///
+ /// 创建通用列表
+ ///
public static UGList Create(RecyclerView recyclerView, Action onItemClick = null) where TData : ISimpleViewData
=> new UGList(recyclerView, onItemClick);
+ ///
+ /// 创建分组列表
+ ///
public static UGGroupList CreateGroup(RecyclerView recyclerView, string groupViewName, Action onItemClick = null) where TData : class, IGroupViewData, new()
=> new UGGroupList(recyclerView, groupViewName, onItemClick);
+ ///
+ /// 创建循环列表
+ ///
public static UGLoopList CreateLoop(RecyclerView recyclerView, Action onItemClick = null) where TData : ISimpleViewData, new()
=> new UGLoopList(recyclerView, onItemClick);
+ ///
+ /// 创建混合列表
+ ///
public static UGMixedList CreateMixed(RecyclerView recyclerView, Action onItemClick = null) where TData : IMixedViewData
=> new UGMixedList(recyclerView, onItemClick);
}
diff --git a/Runtime/RecyclerView/UGListExtensions.cs b/Runtime/RecyclerView/UGListExtensions.cs
index 2940c24..fccf077 100644
--- a/Runtime/RecyclerView/UGListExtensions.cs
+++ b/Runtime/RecyclerView/UGListExtensions.cs
@@ -4,24 +4,25 @@ using UnityEngine;
namespace AlicizaX.UI
{
///
- /// Extension methods for UGList to provide enhanced scrolling functionality
+ /// UGList 扩展方法类
+ /// 提供增强的滚动功能
///
public static class UGListExtensions
{
///
- /// Enable debug logging for ScrollTo operations
+ /// 启用 ScrollTo 操作的调试日志
///
public static bool DebugScrollTo { get; set; } = false;
///
- /// Scrolls to a specific item with alignment and animation options
+ /// 滚动到指定的列表项,支持对齐方式和动画选项
///
- /// The UGList instance
- /// The index of the item to scroll to
- /// How to align the item in the viewport (Start, Center, or End)
- /// Additional offset in pixels to apply after alignment
- /// Whether to animate the scroll
- /// Animation duration in seconds (only used when smooth is true)
+ /// UGList 实例
+ /// 要滚动到的列表项索引
+ /// 列表项在视口中的对齐方式(起始、居中或结束)
+ /// 对齐后额外应用的偏移量(像素)
+ /// 是否使用动画滚动
+ /// 动画持续时间(秒),仅在 smooth 为 true 时使用
public static void ScrollTo(
this UGListBase ugList,
int index,
@@ -47,7 +48,7 @@ namespace AlicizaX.UI
}
///
- /// Scrolls to a specific item and aligns it at the start (top/left) of the viewport
+ /// 滚动到指定的列表项并将其对齐到视口的起始位置(顶部/左侧)
///
public static void ScrollToStart(
this UGListBase ugList,
@@ -62,7 +63,7 @@ namespace AlicizaX.UI
}
///
- /// Scrolls to a specific item and aligns it at the center of the viewport
+ /// 滚动到指定的列表项并将其对齐到视口的中心位置
///
public static void ScrollToCenter(
this UGListBase ugList,
@@ -77,7 +78,7 @@ namespace AlicizaX.UI
}
///
- /// Scrolls to a specific item and aligns it at the end (bottom/right) of the viewport
+ /// 滚动到指定的列表项并将其对齐到视口的结束位置(底部/右侧)
///
public static void ScrollToEnd(
this UGListBase ugList,
diff --git a/Runtime/RecyclerView/ViewHolder/ViewHolder.cs b/Runtime/RecyclerView/ViewHolder/ViewHolder.cs
index 1ff2047..52b60ce 100644
--- a/Runtime/RecyclerView/ViewHolder/ViewHolder.cs
+++ b/Runtime/RecyclerView/ViewHolder/ViewHolder.cs
@@ -5,10 +5,16 @@ using UnityEngine.UI;
namespace AlicizaX.UI
{
+ ///
+ /// 视图持有者基类,用于缓存和复用列表项视图
+ ///
public abstract class ViewHolder : MonoBehaviour
{
private RectTransform rectTransform;
+ ///
+ /// 获取 RectTransform 组件
+ ///
public RectTransform RectTransform
{
get
@@ -23,24 +29,55 @@ namespace AlicizaX.UI
private set { rectTransform = value; }
}
+ ///
+ /// 视图名称,用于区分不同类型的视图
+ ///
public string Name { get; internal set; }
+
+ ///
+ /// 当前绑定的数据索引
+ ///
public int Index { get; internal set; }
+ ///
+ /// 选中状态
+ ///
public bool ChoiseState { private set; get; }
+ ///
+ /// 获取视图的尺寸
+ ///
public Vector2 SizeDelta => RectTransform.sizeDelta;
+
private IButton _button;
+ ///
+ /// 视图首次创建时调用
+ ///
protected internal virtual void OnStart()
{
}
+ ///
+ /// 视图被回收到对象池时调用
+ ///
protected internal virtual void OnRecycled()
{
}
+ ///
+ /// 绑定视图数据(抽象方法,子类必须实现)
+ ///
+ /// 数据类型
+ /// 要绑定的数据
public abstract void BindViewData(T data);
+ ///
+ /// 绑定列表项点击事件
+ ///
+ /// 数据类型
+ /// 数据对象
+ /// 点击回调
protected internal virtual void BindItemClick(T data, Action action)
{
if (_button is null && !TryGetComponent(out _button))
@@ -53,6 +90,10 @@ namespace AlicizaX.UI
_button.onClick.AddListener(() => action?.Invoke(data));
}
+ ///
+ /// 绑定选中状态
+ ///
+ /// 是否选中
protected internal void BindChoiceState(bool state)
{
if (ChoiseState != state)
@@ -62,6 +103,10 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 选中状态改变时的回调(可在子类中重写)
+ ///
+ /// 是否选中
protected internal virtual void OnBindChoiceState(bool state)
{
}
diff --git a/Runtime/RecyclerView/ViewProvider/ViewProvider.cs b/Runtime/RecyclerView/ViewProvider/ViewProvider.cs
index b68bfe2..688ab56 100644
--- a/Runtime/RecyclerView/ViewProvider/ViewProvider.cs
+++ b/Runtime/RecyclerView/ViewProvider/ViewProvider.cs
@@ -5,35 +5,78 @@ namespace AlicizaX.UI
{
///
/// 提供和管理 ViewHolder
+ /// 负责 ViewHolder 的创建、回收和复用
///
public abstract class ViewProvider
{
private readonly List viewHolders = new();
+ ///
+ /// 获取或设置数据适配器
+ ///
public IAdapter Adapter { get; set; }
+
+ ///
+ /// 获取或设置布局管理器
+ ///
public LayoutManager LayoutManager { get; set; }
+ ///
+ /// 获取当前所有活动的 ViewHolder 列表
+ ///
public List ViewHolders => viewHolders;
protected RecyclerView recyclerView;
protected ViewHolder[] templates;
+ ///
+ /// 构造函数
+ ///
+ /// 关联的 RecyclerView 实例
+ /// ViewHolder 模板数组
public ViewProvider(RecyclerView recyclerView, ViewHolder[] templates)
{
this.recyclerView = recyclerView;
this.templates = templates;
}
+ ///
+ /// 根据视图名称获取对应的模板(抽象方法,由子类实现)
+ ///
+ /// 视图名称
+ /// 对应的 ViewHolder 模板
public abstract ViewHolder GetTemplate(string viewName);
+ ///
+ /// 获取所有模板(抽象方法,由子类实现)
+ ///
+ /// 所有 ViewHolder 模板数组
public abstract ViewHolder[] GetTemplates();
+ ///
+ /// 从对象池中分配一个 ViewHolder(抽象方法,由子类实现)
+ ///
+ /// 视图名称
+ /// 分配的 ViewHolder 实例
public abstract ViewHolder Allocate(string viewName);
+ ///
+ /// 将 ViewHolder 回收到对象池(抽象方法,由子类实现)
+ ///
+ /// 视图名称
+ /// 要回收的 ViewHolder
public abstract void Free(string viewName, ViewHolder viewHolder);
+ ///
+ /// 重置 ViewProvider 状态(抽象方法,由子类实现)
+ ///
public abstract void Reset();
+ ///
+ /// 创建指定索引的 ViewHolder
+ /// 从对象池中获取或创建新的 ViewHolder,并进行布局和数据绑定
+ ///
+ /// 数据索引
public void CreateViewHolder(int index)
{
for (int i = index; i < index + LayoutManager.Unit; i++)
@@ -51,6 +94,11 @@ namespace AlicizaX.UI
}
}
+ ///
+ /// 移除指定索引的 ViewHolder
+ /// 将 ViewHolder 从活动列表中移除并回收到对象池
+ ///
+ /// 数据索引
public void RemoveViewHolder(int index)
{
for (int i = index; i < index + LayoutManager.Unit; i++)
@@ -104,6 +152,10 @@ namespace AlicizaX.UI
return -1;
}
+ ///
+ /// 清空所有 ViewHolder
+ /// 将所有活动的 ViewHolder 回收到对象池并清空列表
+ ///
public void Clear()
{
foreach (var viewHolder in viewHolders)
@@ -125,6 +177,10 @@ namespace AlicizaX.UI
return size;
}
+ ///
+ /// 获取数据项总数
+ ///
+ /// 数据项总数,如果没有适配器则返回 0
public int GetItemCount()
{
return Adapter == null ? 0 : Adapter.GetItemCount();