com.alicizax.unity.ui.exten.../Runtime/RecyclerView/Adapter/Adapter.cs
2026-03-11 14:18:07 +08:00

305 lines
8.6 KiB
C#

using System;
using System.Collections.Generic;
namespace AlicizaX.UI
{
/// <summary>
/// RecyclerView 的通用适配器,支持数据绑定、选中状态和列表操作
/// </summary>
/// <typeparam name="T">数据类型,必须实现 ISimpleViewData 接口</typeparam>
public class Adapter<T> : IAdapter where T : ISimpleViewData
{
protected RecyclerView recyclerView;
protected List<T> list;
protected Action<T> onItemClick;
protected int choiceIndex = -1;
/// <summary>
/// 当前选中项的索引
/// </summary>
public int ChoiceIndex
{
get => choiceIndex;
set { SetChoiceIndex(value); }
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="recyclerView">RecyclerView 实例</param>
public Adapter(RecyclerView recyclerView) : this(recyclerView, new List<T>(), null)
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="recyclerView">RecyclerView 实例</param>
/// <param name="list">数据列表</param>
public Adapter(RecyclerView recyclerView, List<T> list) : this(recyclerView, list, null)
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="recyclerView">RecyclerView 实例</param>
/// <param name="list">数据列表</param>
/// <param name="onItemClick">列表项点击回调</param>
public Adapter(RecyclerView recyclerView, List<T> list, Action<T> onItemClick)
{
this.recyclerView = recyclerView;
this.list = list;
this.onItemClick = onItemClick;
}
/// <summary>
/// 获取列表项总数
/// </summary>
public virtual int GetItemCount()
{
return list == null ? 0 : list.Count;
}
/// <summary>
/// 获取实际数据项数量
/// </summary>
public virtual int GetRealCount()
{
return GetItemCount();
}
/// <summary>
/// 获取指定索引位置的视图名称
/// </summary>
public virtual string GetViewName(int index)
{
return "";
}
/// <summary>
/// 绑定视图持有者与数据
/// </summary>
public virtual void OnBindViewHolder(ViewHolder viewHolder, int index)
{
if (index < 0 || index >= GetItemCount()) return;
T data = list[index];
viewHolder.BindViewData(data);
viewHolder.BindItemClick(data, t =>
{
SetChoiceIndex(index);
onItemClick?.Invoke(data);
});
viewHolder.BindChoiceState(index == choiceIndex);
}
/// <summary>
/// 通知数据已更改
/// </summary>
public virtual void NotifyDataChanged()
{
recyclerView.RequestLayout();
recyclerView.Refresh();
}
/// <summary>
/// 设置数据列表并刷新视图
/// </summary>
/// <param name="list">新的数据列表</param>
public virtual void SetList(List<T> list)
{
this.list = list;
recyclerView.Reset();
NotifyDataChanged();
}
/// <summary>
/// 获取指定索引的数据
/// </summary>
/// <param name="index">数据索引</param>
/// <returns>数据对象,索引无效时返回 default</returns>
public T GetData(int index)
{
if (index < 0 || index >= GetItemCount()) return default;
return list[index];
}
/// <summary>
/// 添加单个数据项
/// </summary>
/// <param name="item">要添加的数据项</param>
public void Add(T item)
{
list.Add(item);
NotifyDataChanged();
}
/// <summary>
/// 批量添加数据项
/// </summary>
/// <param name="collection">要添加的数据集合</param>
public void AddRange(IEnumerable<T> collection)
{
list.AddRange(collection);
NotifyDataChanged();
}
/// <summary>
/// 在指定位置插入数据项
/// </summary>
/// <param name="index">插入位置</param>
/// <param name="item">要插入的数据项</param>
public void Insert(int index, T item)
{
list.Insert(index, item);
NotifyDataChanged();
}
/// <summary>
/// 在指定位置批量插入数据项
/// </summary>
/// <param name="index">插入位置</param>
/// <param name="collection">要插入的数据集合</param>
public void InsertRange(int index, IEnumerable<T> collection)
{
list.InsertRange(index, collection);
NotifyDataChanged();
}
/// <summary>
/// 移除指定的数据项
/// </summary>
/// <param name="item">要移除的数据项</param>
public void Remove(T item)
{
int index = list.IndexOf(item);
RemoveAt(index);
}
/// <summary>
/// 移除指定索引位置的数据项
/// </summary>
/// <param name="index">要移除的索引</param>
public void RemoveAt(int index)
{
if (index < 0 || index >= GetItemCount()) return;
list.RemoveAt(index);
NotifyDataChanged();
}
/// <summary>
/// 移除指定范围的数据项
/// </summary>
/// <param name="index">起始索引</param>
/// <param name="count">移除数量</param>
public void RemoveRange(int index, int count)
{
list.RemoveRange(index, count);
NotifyDataChanged();
}
/// <summary>
/// 移除所有符合条件的数据项
/// </summary>
/// <param name="match">匹配条件</param>
public void RemoveAll(Predicate<T> match)
{
list.RemoveAll(match);
NotifyDataChanged();
}
/// <summary>
/// 清空所有数据
/// </summary>
public void Clear()
{
list.Clear();
NotifyDataChanged();
}
/// <summary>
/// 反转指定范围的数据项顺序
/// </summary>
/// <param name="index">起始索引</param>
/// <param name="count">反转数量</param>
public void Reverse(int index, int count)
{
list.Reverse(index, count);
NotifyDataChanged();
}
/// <summary>
/// 反转所有数据项顺序
/// </summary>
public void Reverse()
{
list.Reverse();
NotifyDataChanged();
}
/// <summary>
/// 使用指定的比较器排序数据
/// </summary>
/// <param name="comparison">比较器</param>
public void Sort(Comparison<T> comparison)
{
list.Sort(comparison);
NotifyDataChanged();
}
/// <summary>
/// 设置列表项点击回调
/// </summary>
/// <param name="onItemClick">点击回调</param>
public void SetOnItemClick(Action<T> onItemClick)
{
this.onItemClick = onItemClick;
}
/// <summary>
/// 设置选中项索引
/// </summary>
/// <param name="index">要选中的索引</param>
protected void SetChoiceIndex(int index)
{
if (index == choiceIndex) return;
if (choiceIndex != -1)
{
if (TryGetViewHolder(choiceIndex, out var viewHolder))
{
viewHolder.BindChoiceState(false);
}
}
choiceIndex = index;
if (choiceIndex != -1)
{
if (TryGetViewHolder(choiceIndex, out var viewHolder))
{
viewHolder.BindChoiceState(true);
}
}
}
/// <summary>
/// 尝试获取指定索引的视图持有者
/// </summary>
/// <param name="index">数据索引</param>
/// <param name="viewHolder">输出的视图持有者</param>
/// <returns>是否成功获取</returns>
private bool TryGetViewHolder(int index, out ViewHolder viewHolder)
{
viewHolder = recyclerView.ViewProvider.GetViewHolder(index);
return viewHolder != null;
}
}
}