11
This commit is contained in:
parent
40080636d8
commit
cddf34948d
@ -13,25 +13,28 @@ namespace AlicizaX.UI
|
||||
void Unbind();
|
||||
}
|
||||
|
||||
internal interface IItemRenderInitializer
|
||||
{
|
||||
void Reset(ViewHolder viewHolder);
|
||||
}
|
||||
|
||||
public abstract class ItemRender<TData, THolder> : IItemRender
|
||||
, IItemRenderInitializer
|
||||
where THolder : ViewHolder
|
||||
{
|
||||
private Action defaultClickAction;
|
||||
|
||||
protected ItemRender(THolder holder)
|
||||
{
|
||||
Holder = holder ?? throw new ArgumentNullException(nameof(holder));
|
||||
CurrentIndex = -1;
|
||||
}
|
||||
|
||||
protected THolder Holder { get; }
|
||||
protected THolder Holder { get; private set; }
|
||||
|
||||
protected TData CurrentData { get; private set; }
|
||||
|
||||
protected int CurrentIndex { get; private set; }
|
||||
protected int CurrentIndex { get; private set; } = -1;
|
||||
|
||||
protected bool IsSelected { get; private set; }
|
||||
|
||||
public void Bind(object data, int index, Action defaultClickAction)
|
||||
{
|
||||
EnsureHolder();
|
||||
|
||||
if (data is not TData itemData)
|
||||
{
|
||||
throw new InvalidCastException(
|
||||
@ -47,20 +50,22 @@ namespace AlicizaX.UI
|
||||
|
||||
public void UpdateSelection(bool selected)
|
||||
{
|
||||
EnsureHolder();
|
||||
IsSelected = selected;
|
||||
OnSelectionChanged(selected);
|
||||
}
|
||||
|
||||
public void Unbind()
|
||||
{
|
||||
OnClear();
|
||||
CurrentData = default;
|
||||
CurrentIndex = -1;
|
||||
defaultClickAction = null;
|
||||
Holder.ClearInteractionCallbacks();
|
||||
ResetState();
|
||||
}
|
||||
|
||||
protected abstract void Bind(TData data, int index);
|
||||
|
||||
protected virtual void OnHolderChanged()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnSelectionChanged(bool selected)
|
||||
{
|
||||
}
|
||||
@ -96,19 +101,63 @@ namespace AlicizaX.UI
|
||||
{
|
||||
OnPointerExit();
|
||||
}
|
||||
|
||||
void IItemRenderInitializer.Reset(ViewHolder viewHolder)
|
||||
{
|
||||
if (viewHolder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(viewHolder));
|
||||
}
|
||||
|
||||
if (viewHolder is not THolder holder)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"RecyclerView item render '{GetType().FullName}' expects holder '{typeof(THolder).FullName}', but got '{viewHolder.GetType().FullName}'.");
|
||||
}
|
||||
|
||||
ResetState();
|
||||
Holder = holder;
|
||||
OnHolderChanged();
|
||||
}
|
||||
|
||||
private void EnsureHolder()
|
||||
{
|
||||
if (Holder == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"RecyclerView item render '{GetType().FullName}' has not been initialized with a holder.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetState()
|
||||
{
|
||||
if (Holder != null)
|
||||
{
|
||||
if (IsSelected)
|
||||
{
|
||||
IsSelected = false;
|
||||
OnSelectionChanged(false);
|
||||
}
|
||||
|
||||
OnClear();
|
||||
Holder.ClearInteractionCallbacks();
|
||||
}
|
||||
|
||||
CurrentData = default;
|
||||
CurrentIndex = -1;
|
||||
IsSelected = false;
|
||||
defaultClickAction = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ItemRenderResolver
|
||||
{
|
||||
internal sealed class ItemRenderDefinition
|
||||
{
|
||||
private readonly ConstructorInfo constructor;
|
||||
|
||||
public ItemRenderDefinition(Type itemRenderType, Type holderType, ConstructorInfo constructor)
|
||||
public ItemRenderDefinition(Type itemRenderType, Type holderType)
|
||||
{
|
||||
ItemRenderType = itemRenderType;
|
||||
HolderType = holderType;
|
||||
this.constructor = constructor;
|
||||
}
|
||||
|
||||
public Type ItemRenderType { get; }
|
||||
@ -128,7 +177,20 @@ namespace AlicizaX.UI
|
||||
$"RecyclerView item render '{ItemRenderType.FullName}' expects holder '{HolderType.FullName}', but got '{viewHolder.GetType().FullName}'.");
|
||||
}
|
||||
|
||||
return (IItemRender)constructor.Invoke(new object[] { viewHolder });
|
||||
if (Activator.CreateInstance(ItemRenderType, true) is not IItemRender itemRender)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"RecyclerView item render '{ItemRenderType.FullName}' could not be created.");
|
||||
}
|
||||
|
||||
if (itemRender is not IItemRenderInitializer initializer)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"RecyclerView item render '{ItemRenderType.FullName}' must inherit from ItemRender<TData, THolder>.");
|
||||
}
|
||||
|
||||
initializer.Reset(viewHolder);
|
||||
return itemRender;
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,16 +233,16 @@ namespace AlicizaX.UI
|
||||
ConstructorInfo constructor = itemRenderType.GetConstructor(
|
||||
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
|
||||
null,
|
||||
new[] { holderType },
|
||||
Type.EmptyTypes,
|
||||
null);
|
||||
|
||||
if (constructor == null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"RecyclerView item render '{itemRenderType.FullName}' must declare a constructor with a single '{holderType.FullName}' parameter.");
|
||||
$"RecyclerView item render '{itemRenderType.FullName}' must have a parameterless constructor.");
|
||||
}
|
||||
|
||||
return new ItemRenderDefinition(itemRenderType, holderType, constructor);
|
||||
return new ItemRenderDefinition(itemRenderType, holderType);
|
||||
}
|
||||
|
||||
private static bool TryGetHolderType(Type itemRenderType, out Type holderType)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user