2025-03-12 20:59:12 +08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
2025-11-20 15:40:38 +08:00
|
|
|
|
namespace AlicizaX.UI
|
2025-03-12 20:59:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 提供和管理 ViewHolder
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// 负责 ViewHolder 的创建、回收和复用
|
2025-03-12 20:59:12 +08:00
|
|
|
|
/// </summary>
|
2025-12-26 14:22:46 +08:00
|
|
|
|
public abstract class ViewProvider
|
2025-03-12 20:59:12 +08:00
|
|
|
|
{
|
|
|
|
|
|
private readonly List<ViewHolder> viewHolders = new();
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取或设置数据适配器
|
|
|
|
|
|
/// </summary>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public IAdapter Adapter { get; set; }
|
2026-03-11 14:18:07 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取或设置布局管理器
|
|
|
|
|
|
/// </summary>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public LayoutManager LayoutManager { get; set; }
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取当前所有活动的 ViewHolder 列表
|
|
|
|
|
|
/// </summary>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public List<ViewHolder> ViewHolders => viewHolders;
|
|
|
|
|
|
|
|
|
|
|
|
protected RecyclerView recyclerView;
|
|
|
|
|
|
protected ViewHolder[] templates;
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 构造函数
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="recyclerView">关联的 RecyclerView 实例</param>
|
|
|
|
|
|
/// <param name="templates">ViewHolder 模板数组</param>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public ViewProvider(RecyclerView recyclerView, ViewHolder[] templates)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.recyclerView = recyclerView;
|
|
|
|
|
|
this.templates = templates;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据视图名称获取对应的模板(抽象方法,由子类实现)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="viewName">视图名称</param>
|
|
|
|
|
|
/// <returns>对应的 ViewHolder 模板</returns>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public abstract ViewHolder GetTemplate(string viewName);
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取所有模板(抽象方法,由子类实现)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>所有 ViewHolder 模板数组</returns>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public abstract ViewHolder[] GetTemplates();
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 从对象池中分配一个 ViewHolder(抽象方法,由子类实现)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="viewName">视图名称</param>
|
|
|
|
|
|
/// <returns>分配的 ViewHolder 实例</returns>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public abstract ViewHolder Allocate(string viewName);
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 将 ViewHolder 回收到对象池(抽象方法,由子类实现)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="viewName">视图名称</param>
|
|
|
|
|
|
/// <param name="viewHolder">要回收的 ViewHolder</param>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public abstract void Free(string viewName, ViewHolder viewHolder);
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 重置 ViewProvider 状态(抽象方法,由子类实现)
|
|
|
|
|
|
/// </summary>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public abstract void Reset();
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建指定索引的 ViewHolder
|
|
|
|
|
|
/// 从对象池中获取或创建新的 ViewHolder,并进行布局和数据绑定
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="index">数据索引</param>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public void CreateViewHolder(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = index; i < index + LayoutManager.Unit; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (i > Adapter.GetItemCount() - 1) break;
|
|
|
|
|
|
|
|
|
|
|
|
string viewName = Adapter.GetViewName(i);
|
|
|
|
|
|
var viewHolder = Allocate(viewName);
|
|
|
|
|
|
viewHolder.Name = viewName;
|
|
|
|
|
|
viewHolder.Index = i;
|
|
|
|
|
|
viewHolders.Add(viewHolder);
|
2025-12-26 14:22:46 +08:00
|
|
|
|
|
2025-03-12 20:59:12 +08:00
|
|
|
|
LayoutManager.Layout(viewHolder, i);
|
|
|
|
|
|
Adapter.OnBindViewHolder(viewHolder, i);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 移除指定索引的 ViewHolder
|
|
|
|
|
|
/// 将 ViewHolder 从活动列表中移除并回收到对象池
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="index">数据索引</param>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public void RemoveViewHolder(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = index; i < index + LayoutManager.Unit; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (i > Adapter.GetItemCount() - 1) break;
|
|
|
|
|
|
|
|
|
|
|
|
int viewHolderIndex = GetViewHolderIndex(i);
|
|
|
|
|
|
|
|
|
|
|
|
if (viewHolderIndex < 0 || viewHolderIndex >= viewHolders.Count) return;
|
|
|
|
|
|
|
|
|
|
|
|
var viewHolder = viewHolders[viewHolderIndex];
|
|
|
|
|
|
viewHolders.RemoveAt(viewHolderIndex);
|
2025-05-30 13:43:08 +08:00
|
|
|
|
viewHolder.OnRecycled();
|
2025-03-12 20:59:12 +08:00
|
|
|
|
Free(viewHolder.Name, viewHolder);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据数据的下标获取对应的 ViewHolder
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="index">数据的下标</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public ViewHolder GetViewHolder(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var viewHolder in viewHolders)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (viewHolder.Index == index)
|
|
|
|
|
|
{
|
|
|
|
|
|
return viewHolder;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-01 15:21:02 +08:00
|
|
|
|
|
2025-03-12 20:59:12 +08:00
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 根据数据的下标获取 ViewHolder 的下标
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="index">数据的下标</param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public int GetViewHolderIndex(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < viewHolders.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (viewHolders[i].Index == index)
|
|
|
|
|
|
{
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-01 15:21:02 +08:00
|
|
|
|
|
2025-03-12 20:59:12 +08:00
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 清空所有 ViewHolder
|
|
|
|
|
|
/// 将所有活动的 ViewHolder 回收到对象池并清空列表
|
|
|
|
|
|
/// </summary>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public void Clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var viewHolder in viewHolders)
|
|
|
|
|
|
{
|
|
|
|
|
|
Free(viewHolder.Name, viewHolder);
|
|
|
|
|
|
}
|
2025-04-01 15:21:02 +08:00
|
|
|
|
|
2025-03-12 20:59:12 +08:00
|
|
|
|
viewHolders.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 计算 ViewHolder 的尺寸
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="index"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public Vector2 CalculateViewSize(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector2 size = GetTemplate(Adapter.GetViewName(index)).SizeDelta;
|
|
|
|
|
|
return size;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-11 14:18:07 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取数据项总数
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns>数据项总数,如果没有适配器则返回 0</returns>
|
2025-03-12 20:59:12 +08:00
|
|
|
|
public int GetItemCount()
|
|
|
|
|
|
{
|
|
|
|
|
|
return Adapter == null ? 0 : Adapter.GetItemCount();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|