Grouped ListView, Grouped TileView
You can create grouped ListView with GroupedList<TItem>
(group items does not exists and will be automatically created) or LinearGroupedList<TItem>
(group items already exists in DataSource
).
Grouped ListView
public class GroupedItem
{
public string Name;
public bool IsGroup = false;
public bool IsEmpty = false;
}
public class GroupedItems : GroupedList<GroupedItem>
{
/// <summary>
/// Get group for specified item.
/// </summary>
/// <param name="item">Item.</param>
/// <returns>Group for specified item.</returns>
protected override GroupedItem GetGroup(GroupedItem item)
{
var name = item.Name.Length > 0 ? item.Name[0].ToString() : string.Empty;
foreach (var key in GroupsWithItems.Keys)
{
if (key.Name == name)
{
return key;
}
}
return new GroupedItem() { Name = name, IsGroup = true, };
}
}
public class GroupedView : ListViewCustom<GroupedListViewComponent, GroupedItem>
{
// GroupedData used to add and remove items instead of the DataSource.
public GroupedItems GroupedData = new GroupedItems();
bool isGroupedViewInited;
public override void Init()
{
if (isGroupedViewInited)
{
return;
}
isGroupedViewInited = true;
base.Init();
GroupedData.GroupComparison = (x, y) => x.Name.CompareTo(y.Name);
GroupedData.Data = DataSource;
CanSelect = index => !DataSource[index].IsGroup;
}
}
Grouped TileView
using UIWidgets;
using UnityEngine;
public class GroupedTileView : ListViewCustom<GroupedListViewComponent, GroupedItem>
{
public GroupedItems GroupedData = new GroupedItems();
[SerializeField]
protected GroupedListViewComponent HeaderTemplate;
[SerializeField]
protected GroupedListViewComponent HeaderEmptyTemplate;
[SerializeField]
protected GroupedListViewComponent ItemTemplate;
[SerializeField]
protected GroupedListViewComponent ItemEmptyTemplate;
class Selector : IListViewTemplateSelector<GroupedListViewComponent, GroupedItem>
{
GroupedListViewComponent headerTemplate;
GroupedListViewComponent headerEmptyTemplate;
GroupedListViewComponent itemTemplate;
GroupedListViewComponent itemEmptyTemplate;
GroupedListViewComponent[] templates;
public Selector(
GroupedListViewComponent headerTemplate,
GroupedListViewComponent headerEmptyTemplate,
GroupedListViewComponent itemTemplate,
GroupedListViewComponent itemEmptyTemplate)
{
this.headerTemplate = headerTemplate;
this.headerEmptyTemplate = headerEmptyTemplate;
this.itemTemplate = itemTemplate;
this.itemEmptyTemplate = itemEmptyTemplate;
templates = new[] { this.headerTemplate, this.headerEmptyTemplate, this.itemTemplate, this.itemEmptyTemplate, };
}
public GroupedListViewComponent[] AllTemplates() => templates;
public GroupedListViewComponent Select(int index, GroupedItem item)
{
if (item.IsGroup)
{
return item.IsEmpty ? headerEmptyTemplate : headerTemplate;
}
else
{
return item.IsEmpty ? itemEmptyTemplate : itemTemplate;
}
}
}
bool isGroupedListViewInited;
public override void Init()
{
if (isGroupedListViewInited)
{
return;
}
isGroupedListViewInited = true;
TemplateSelector = new Selector(HeaderTemplate, HeaderEmptyTemplate, ItemTemplate, ItemEmptyTemplate);
base.Init();
GroupedData.GroupComparison = (x, y) => x.Created.CompareTo(y.Created);
GroupedData.Data = DataSource;
GroupedData.EmptyGroupItem = new Photo() { IsGroup = true, IsEmpty = true };
GroupedData.EmptyItem = new Photo() { IsEmpty = true };
GroupedData.ItemsPerBlock = ListRenderer.GetItemsPerBlock();
}
public override void UpdateItems()
{
base.UpdateItems();
GroupedData.ItemsPerBlock = ListRenderer.GetItemsPerBlock();
}
public override void Resize()
{
base.Resize();
GroupedData.ItemsPerBlock = ListRenderer.GetItemsPerBlock();
}
}
Linear GroupedTileView
public class LinearGroupedTileView : ListViewCustom<GroupedListViewComponent, GroupedItem>
{
// Real DataSource (use instead of DataSource).
public ObservableList<GroupedItem> RealDataSource = new ObservableList<GroupedItem>();
public LinearGroupedList<GroupedItem> GroupedData = new LinearGroupedList<GroupedItem>(x => x.IsGroup);
[SerializeField]
protected GroupedListViewComponent HeaderTemplate;
[SerializeField]
protected GroupedListViewComponent HeaderEmptyTemplate;
[SerializeField]
protected GroupedListViewComponent ItemTemplate;
[SerializeField]
protected GroupedListViewComponent ItemEmptyTemplate;
class Selector : IListViewTemplateSelector<GroupedListViewComponent, GroupedItem>
{
GroupedListViewComponent headerTemplate;
GroupedListViewComponent headerEmptyTemplate;
GroupedListViewComponent itemTemplate;
GroupedListViewComponent itemEmptyTemplate;
GroupedListViewComponent[] templates;
public Selector(
GroupedListViewComponent headerTemplate,
GroupedListViewComponent headerEmptyTemplate,
GroupedListViewComponent itemTemplate,
GroupedListViewComponent itemEmptyTemplate)
{
this.headerTemplate = headerTemplate;
this.headerEmptyTemplate = headerEmptyTemplate;
this.itemTemplate = itemTemplate;
this.itemEmptyTemplate = itemEmptyTemplate;
templates = new[] { this.headerTemplate, this.headerEmptyTemplate, this.itemTemplate, this.itemEmptyTemplate, };
}
public GroupedListViewComponent[] AllTemplates() => templates;
public GroupedListViewComponent Select(int index, GroupedItem item)
{
if (item.IsGroup)
{
return item.IsEmpty ? headerEmptyTemplate : headerTemplate;
}
else
{
return item.IsEmpty ? itemEmptyTemplate : itemTemplate;
}
}
}
bool isGroupedListViewInited;
public override void Init()
{
if (isGroupedListViewInited)
{
return;
}
isGroupedListViewInited = true;
TemplateSelector = new Selector(HeaderTemplate, HeaderEmptyTemplate, ItemTemplate, ItemEmptyTemplate);
base.Init();
GroupedData.EmptyHeaderItem = new GroupedItem() { IsGroup = true, IsEmpty = true };
GroupedData.EmptyItem = new GroupedItem() { IsEmpty = true };
GroupedData.ItemsPerBlock = ListRenderer.GetItemsPerBlock();
GroupedData.Input = RealDataSource;
GroupedData.Output = DataSource;
}
public override void UpdateItems()
{
base.UpdateItems();
GroupedData.ItemsPerBlock = ListRenderer.GetItemsPerBlock();
}
public override void Resize()
{
base.Resize();
GroupedData.ItemsPerBlock = ListRenderer.GetItemsPerBlock();
}
}