2025-03-12 20:59:12 +08:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
2025-11-20 15:40:38 +08:00
|
|
|
namespace AlicizaX.UI
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
2025-11-20 15:40:38 +08:00
|
|
|
public class GroupAdapter<TData> : Adapter<TData> where TData : IGroupViewData, new()
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
2025-11-20 15:40:38 +08:00
|
|
|
private readonly List<TData> showList = new();
|
2026-03-27 18:38:29 +08:00
|
|
|
private readonly string groupViewName;
|
2025-03-12 20:59:12 +08:00
|
|
|
|
|
|
|
|
public GroupAdapter(RecyclerView recyclerView, string groupViewName) : base(recyclerView)
|
|
|
|
|
{
|
|
|
|
|
this.groupViewName = groupViewName;
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 15:40:38 +08:00
|
|
|
public GroupAdapter(RecyclerView recyclerView, List<TData> list) : base(recyclerView, list)
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-20 15:40:38 +08:00
|
|
|
public GroupAdapter(RecyclerView recyclerView) : base(recyclerView)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-12 20:59:12 +08:00
|
|
|
public override int GetItemCount()
|
|
|
|
|
{
|
|
|
|
|
return showList.Count;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 14:43:37 +08:00
|
|
|
public override int GetRealCount()
|
|
|
|
|
{
|
|
|
|
|
return showList.Count;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-12 20:59:12 +08:00
|
|
|
public override string GetViewName(int index)
|
|
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
return index >= 0 && index < showList.Count
|
|
|
|
|
? showList[index].TemplateName
|
|
|
|
|
: string.Empty;
|
2025-03-12 20:59:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void NotifyDataChanged()
|
|
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
if (string.IsNullOrEmpty(groupViewName))
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
throw new InvalidOperationException("GroupAdapter requires a non-empty groupViewName.");
|
2025-03-12 20:59:12 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-31 15:18:50 +08:00
|
|
|
if (list == null)
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
showList.Clear();
|
|
|
|
|
base.NotifyDataChanged();
|
|
|
|
|
return;
|
2025-03-12 20:59:12 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-31 15:18:50 +08:00
|
|
|
for (int i = 0; i < list.Count; i++)
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
CreateGroup(list[i].Type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < showList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
TData group = showList[i];
|
|
|
|
|
if (group.TemplateName != groupViewName)
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 14:43:37 +08:00
|
|
|
CollapseInternal(i);
|
2026-03-31 15:18:50 +08:00
|
|
|
if (group.Expanded)
|
|
|
|
|
{
|
2026-04-01 14:43:37 +08:00
|
|
|
ExpandInternal(i);
|
2026-03-31 15:18:50 +08:00
|
|
|
i += CountItemsForType(group.Type);
|
2025-03-12 20:59:12 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-31 15:18:50 +08:00
|
|
|
RemoveEmptyGroups();
|
2025-03-12 20:59:12 +08:00
|
|
|
base.NotifyDataChanged();
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-26 14:22:46 +08:00
|
|
|
public override void SetList(List<TData> list)
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
|
|
|
|
showList.Clear();
|
|
|
|
|
base.SetList(list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void CreateGroup(int type)
|
|
|
|
|
{
|
2025-11-20 15:40:38 +08:00
|
|
|
var groupData = showList.Find(data => data.Type == type && data.TemplateName == groupViewName);
|
2025-03-12 20:59:12 +08:00
|
|
|
if (groupData == null)
|
|
|
|
|
{
|
2025-11-20 15:40:38 +08:00
|
|
|
groupData = new TData
|
|
|
|
|
{
|
|
|
|
|
TemplateName = groupViewName,
|
|
|
|
|
Type = type
|
|
|
|
|
};
|
2025-03-12 20:59:12 +08:00
|
|
|
showList.Add(groupData);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Expand(int index)
|
2026-04-01 14:43:37 +08:00
|
|
|
{
|
|
|
|
|
SetExpanded(index, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Collapse(int index)
|
|
|
|
|
{
|
|
|
|
|
SetExpanded(index, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool SetExpanded(int index, bool expanded)
|
|
|
|
|
{
|
|
|
|
|
if (!TryGetDisplayData(index, out TData data) || !IsGroupIndex(index))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data.Expanded = expanded;
|
|
|
|
|
NotifyDataChanged();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsGroupIndex(int index)
|
|
|
|
|
{
|
|
|
|
|
return index >= 0 &&
|
|
|
|
|
index < showList.Count &&
|
|
|
|
|
string.Equals(showList[index].TemplateName, groupViewName, StringComparison.Ordinal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool TryGetDisplayData(int index, out TData data)
|
|
|
|
|
{
|
|
|
|
|
if (list == null || index < 0 || index >= showList.Count)
|
|
|
|
|
{
|
|
|
|
|
data = default;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data = showList[index];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ExpandInternal(int index)
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
if (list == null || index < 0 || index >= showList.Count)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int type = showList[index].Type;
|
|
|
|
|
for (int i = 0; i < list.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (list[i].Type == type)
|
|
|
|
|
{
|
|
|
|
|
showList.Insert(index + 1, list[i]);
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-03-12 20:59:12 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-01 14:43:37 +08:00
|
|
|
private void CollapseInternal(int index)
|
2025-03-12 20:59:12 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
if (index < 0 || index >= showList.Count)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int type = showList[index].Type;
|
|
|
|
|
int removeCount = 0;
|
|
|
|
|
for (int i = index + 1; i < showList.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (showList[i].TemplateName == groupViewName || showList[i].Type != type)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
removeCount++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (removeCount > 0)
|
|
|
|
|
{
|
|
|
|
|
showList.RemoveRange(index + 1, removeCount);
|
|
|
|
|
}
|
2025-03-12 20:59:12 +08:00
|
|
|
}
|
2026-03-27 18:38:29 +08:00
|
|
|
|
|
|
|
|
protected override bool TryGetBindData(int index, out TData data)
|
|
|
|
|
{
|
|
|
|
|
if (index < 0 || index >= showList.Count)
|
|
|
|
|
{
|
|
|
|
|
data = default;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data = showList[index];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-31 15:18:50 +08:00
|
|
|
public void Activate(int index)
|
2026-03-27 18:38:29 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
if (index < 0 || index >= showList.Count)
|
2026-03-27 18:38:29 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TData data = showList[index];
|
2026-04-01 14:43:37 +08:00
|
|
|
if (IsGroupIndex(index))
|
2026-03-31 15:18:50 +08:00
|
|
|
{
|
2026-04-01 14:43:37 +08:00
|
|
|
SetExpanded(index, !data.Expanded);
|
2026-03-31 15:18:50 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SetChoiceIndex(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private int CountItemsForType(int type)
|
|
|
|
|
{
|
|
|
|
|
if (list == null)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
for (int i = 0; i < list.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (list[i].Type == type)
|
|
|
|
|
{
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RemoveEmptyGroups()
|
|
|
|
|
{
|
|
|
|
|
for (int i = showList.Count - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
TData group = showList[i];
|
|
|
|
|
if (group.TemplateName != groupViewName)
|
2026-03-27 18:38:29 +08:00
|
|
|
{
|
2026-03-31 15:18:50 +08:00
|
|
|
continue;
|
2026-03-27 18:38:29 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-31 15:18:50 +08:00
|
|
|
if (CountItemsForType(group.Type) == 0)
|
|
|
|
|
{
|
|
|
|
|
showList.RemoveAt(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-27 18:38:29 +08:00
|
|
|
}
|
2025-03-12 20:59:12 +08:00
|
|
|
}
|
|
|
|
|
}
|