This commit is contained in:
陈思海 2025-12-26 14:22:46 +08:00
parent fc993a1dbe
commit 26c205ddc0
39 changed files with 1273 additions and 1004 deletions

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ GameObject:
- component: {fileID: 409256563818501030} - component: {fileID: 409256563818501030}
- component: {fileID: 4967247000384896254} - component: {fileID: 4967247000384896254}
- component: {fileID: 2527097672867102998} - component: {fileID: 2527097672867102998}
- component: {fileID: 144409482669617178} - component: {fileID: 222070472718835377}
m_Layer: 5 m_Layer: 5
m_Name: ScrollView m_Name: ScrollView
m_TagString: Untagged m_TagString: Untagged
@ -90,9 +90,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7efd8e83d2092b347952108134dc37eb, type: 3} m_Script: {fileID: 11500000, guid: 7efd8e83d2092b347952108134dc37eb, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
direction: 1 direction: 0
alignment: 1 alignment: 1
content: {fileID: 7227160576944475251}
spacing: {x: 0, y: 0} spacing: {x: 0, y: 0}
padding: {x: 0, y: 0} padding: {x: 0, y: 0}
scroll: 1 scroll: 1
@ -100,20 +99,21 @@ MonoBehaviour:
scrollSpeed: 10 scrollSpeed: 10
wheelSpeed: 30 wheelSpeed: 30
templates: [] templates: []
_scrollerTypeName: AlicizaX.UI.RecyclerView.Scroller content: {fileID: 7227160576944475251}
_scroller: {fileID: 144409482669617178} showScrollBar: 0
_showScrollBar: 0 scrollbar: {fileID: 0}
_scrollbar: {fileID: 0}
_layoutManagerTypeName: AlicizaX.UI.LinearLayoutManager _layoutManagerTypeName: AlicizaX.UI.LinearLayoutManager
_layoutManager: layoutManager:
rid: 7492395943315111994 rid: 6739296571988901898
_scrollerTypeName: AlicizaX.UI.Scroller
scroller: {fileID: 222070472718835377}
references: references:
version: 2 version: 2
RefIds: RefIds:
- rid: 7492395943315111994 - rid: 6739296571988901898
type: {class: LinearLayoutManager, ns: AlicizaX.UI, asm: AlicizaX.UI.Extension} type: {class: LinearLayoutManager, ns: AlicizaX.UI, asm: AlicizaX.UI.Extension}
data: data:
--- !u!114 &144409482669617178 --- !u!114 &222070472718835377
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
@ -125,6 +125,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7b7de4cb3a1546e4a9ade6b8dbf8af92, type: 3} m_Script: {fileID: 11500000, guid: 7b7de4cb3a1546e4a9ade6b8dbf8af92, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
dragStopTime: 0
--- !u!1 &9220717789715235424 --- !u!1 &9220717789715235424
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -69,7 +69,7 @@ namespace AlicizaX.UI
recyclerView.Refresh(); recyclerView.Refresh();
} }
protected internal virtual void SetList(List<T> list) public virtual void SetList(List<T> list)
{ {
this.list = list; this.list = list;
recyclerView.Reset(); recyclerView.Reset();

View File

@ -87,7 +87,7 @@ namespace AlicizaX.UI
base.NotifyDataChanged(); base.NotifyDataChanged();
} }
protected internal override void SetList(List<TData> list) public override void SetList(List<TData> list)
{ {
showList.Clear(); showList.Clear();
base.SetList(list); base.SetList(list);

View File

@ -1,3 +1,3 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 05736c35a54b467a966b416c1461ba61 guid: d43a3e6aece04b86ab8eb139abb89e46
timeCreated: 1763617414 timeCreated: 1766661642

View File

@ -1,3 +1,3 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: a059b7119e284e37a88a569f76b40579 guid: cacaed2312884ce9ba739399b8271b93
timeCreated: 1763617420 timeCreated: 1766661647

View File

@ -1,3 +1,3 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: d42e2db77425447490cb9f68003e818b guid: fdf59811e23f47f19be6398684473df2
timeCreated: 1741771999 timeCreated: 1766647995

View File

@ -1,48 +0,0 @@
using System;
using UnityEngine;
namespace AlicizaX.UI
{
[Serializable]
public class AlignableLinearLayoutManager : LinearLayoutManager
{
[SerializeField] private float alignmentCount = 0f; // 对齐比例 (0=顶部, 1=底部, 0.5=居中)
public override Vector2 CalculatePosition(int index)
{
float position;
if (direction == Direction.Vertical)
{
position = index * (lineHeight + spacing.y) - ScrollPosition ;
return new Vector2(0, position + padding.y);
}
position = index * (lineHeight + spacing.x) - ScrollPosition ;
var a = new Vector2(position + padding.x, 0);
return a;
}
public override float IndexToPosition(int index)
{
if (index < 0 || index >= adapter.GetItemCount()) return 0;
float len, viewLength, position;
if (direction == Direction.Vertical)
{
len = index * (lineHeight + spacing.y) - ((lineHeight + spacing.y) * alignmentCount);
viewLength = viewportSize.y;
position = len + viewLength > contentSize.y ? contentSize.y - viewportSize.y : len;
}
else
{
len = index * (lineHeight + spacing.x);
viewLength = viewportSize.x;
position = len + viewLength > contentSize.x ? contentSize.x - viewportSize.x : len;
}
return position;
}
}
}

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: e5cb3f76e0f84a7aa75959e194f524b5
timeCreated: 1748588163

View File

@ -3,23 +3,20 @@ using UnityEngine;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
[System.Serializable]
public class CircleLayoutManager : LayoutManager public class CircleLayoutManager : LayoutManager
{ {
private float radius;
private float intervalAngle;
private new CircleDirection direction;
[SerializeField] [SerializeField]
private CircleDirection circleDirection= CircleDirection.Positive;
[SerializeField]
private float intervalAngle=0;
private float radius;
private float initalAngle; private float initalAngle;
public CircleLayoutManager(CircleDirection direction = CircleDirection.Positive)
{
this.direction = direction;
}
public CircleLayoutManager() public CircleLayoutManager()
{ {
} }
public override Vector2 CalculateContentSize() public override Vector2 CalculateContentSize()
@ -49,7 +46,7 @@ namespace AlicizaX.UI
public override Vector2 CalculatePosition(int index) public override Vector2 CalculatePosition(int index)
{ {
float angle = index * intervalAngle; float angle = index * intervalAngle;
angle = direction == CircleDirection.Positive ? angle : -angle; angle = circleDirection == CircleDirection.Positive ? angle : -angle;
angle += initalAngle + ScrollPosition; angle += initalAngle + ScrollPosition;
float radian = angle * (Mathf.PI / 180f); float radian = angle * (Mathf.PI / 180f);
float x = radius * Mathf.Sin(radian); float x = radius * Mathf.Sin(radian);
@ -97,7 +94,7 @@ namespace AlicizaX.UI
for (int i = 0; i < viewHolders.Count; i++) for (int i = 0; i < viewHolders.Count; i++)
{ {
float angle = i * intervalAngle + initalAngle; float angle = i * intervalAngle + initalAngle;
angle = direction == CircleDirection.Positive ? angle + ScrollPosition : angle - ScrollPosition; angle = circleDirection == CircleDirection.Positive ? angle + ScrollPosition : angle - ScrollPosition;
float delta = (angle - initalAngle) % 360; float delta = (angle - initalAngle) % 360;
delta = delta < 0 ? delta + 360 : delta; delta = delta < 0 ? delta + 360 : delta;
delta = delta > 180 ? 360 - delta : delta; delta = delta > 180 ? 360 - delta : delta;

View File

@ -1,18 +1,17 @@
using System;
using UnityEngine; using UnityEngine;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
[Serializable] [System.Serializable]
public class GridLayoutManager : LayoutManager public class GridLayoutManager : LayoutManager
{ {
private Vector2 cellSize; private Vector2 cellSize;
[SerializeField] private int cellCount; [SerializeField] private int cellCounnt = 1;
public GridLayoutManager() public GridLayoutManager()
{ {
unit = cellCount; this.unit = cellCounnt;
} }
public override Vector2 CalculateContentSize() public override Vector2 CalculateContentSize()
@ -63,7 +62,6 @@ namespace AlicizaX.UI
width = viewportSize.x; width = viewportSize.x;
height = viewportSize.y; height = viewportSize.y;
} }
return new Vector2((width - cellSize.x) / 2, (height - cellSize.y) / 2); return new Vector2((width - cellSize.x) / 2, (height - cellSize.y) / 2);
} }
@ -80,7 +78,6 @@ namespace AlicizaX.UI
width = viewportSize.x; width = viewportSize.x;
height = viewportSize.y; height = viewportSize.y;
} }
return new Vector2((width - cellSize.x) / 2, (height - cellSize.y) / 2); return new Vector2((width - cellSize.x) / 2, (height - cellSize.y) / 2);
} }

View File

@ -1,13 +1,11 @@
using System;
using UnityEngine; using UnityEngine;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
[Serializable] [System.Serializable]
public abstract class LayoutManager : ILayoutManager public abstract class LayoutManager : ILayoutManager
{ {
protected Vector2 viewportSize; protected Vector2 viewportSize;
public Vector2 ViewportSize public Vector2 ViewportSize
{ {
get => viewportSize; get => viewportSize;
@ -15,7 +13,6 @@ namespace AlicizaX.UI
} }
protected Vector2 contentSize; protected Vector2 contentSize;
public Vector2 ContentSize public Vector2 ContentSize
{ {
get => contentSize; get => contentSize;
@ -23,7 +20,6 @@ namespace AlicizaX.UI
} }
protected Vector2 contentOffset; protected Vector2 contentOffset;
public Vector2 ContentOffset public Vector2 ContentOffset
{ {
get => contentOffset; get => contentOffset;
@ -31,7 +27,6 @@ namespace AlicizaX.UI
} }
protected Vector2 viewportOffset; protected Vector2 viewportOffset;
public Vector2 ViewportOffset public Vector2 ViewportOffset
{ {
get => viewportOffset; get => viewportOffset;
@ -39,7 +34,6 @@ namespace AlicizaX.UI
} }
protected IAdapter adapter; protected IAdapter adapter;
public IAdapter Adapter public IAdapter Adapter
{ {
get => adapter; get => adapter;
@ -47,7 +41,6 @@ namespace AlicizaX.UI
} }
protected ViewProvider viewProvider; protected ViewProvider viewProvider;
public ViewProvider ViewProvider public ViewProvider ViewProvider
{ {
get => viewProvider; get => viewProvider;
@ -55,7 +48,6 @@ namespace AlicizaX.UI
} }
protected RecyclerView recyclerView; protected RecyclerView recyclerView;
public virtual RecyclerView RecyclerView public virtual RecyclerView RecyclerView
{ {
get => recyclerView; get => recyclerView;
@ -63,7 +55,6 @@ namespace AlicizaX.UI
} }
protected Direction direction; protected Direction direction;
public Direction Direction public Direction Direction
{ {
get => direction; get => direction;
@ -71,7 +62,6 @@ namespace AlicizaX.UI
} }
protected Alignment alignment; protected Alignment alignment;
public Alignment Alignment public Alignment Alignment
{ {
get => alignment; get => alignment;
@ -79,7 +69,6 @@ namespace AlicizaX.UI
} }
protected Vector2 spacing; protected Vector2 spacing;
public Vector2 Spacing public Vector2 Spacing
{ {
get => spacing; get => spacing;
@ -87,7 +76,6 @@ namespace AlicizaX.UI
} }
protected Vector2 padding; protected Vector2 padding;
public Vector2 Padding public Vector2 Padding
{ {
get => padding; get => padding;
@ -95,26 +83,16 @@ namespace AlicizaX.UI
} }
protected int unit = 1; protected int unit = 1;
public int Unit public int Unit
{ {
get => unit; get => unit;
set => unit = value; set => unit = value;
} }
protected bool canScroll;
public bool CanScroll
{
get => canScroll;
set => canScroll = value;
}
public float ScrollPosition => recyclerView.GetScrollPosition(); public float ScrollPosition => recyclerView.GetScrollPosition();
public LayoutManager() public LayoutManager() { }
{
}
public void SetContentSize() public void SetContentSize()
{ {
@ -135,7 +113,9 @@ namespace AlicizaX.UI
public virtual void Layout(ViewHolder viewHolder, int index) public virtual void Layout(ViewHolder viewHolder, int index)
{ {
Vector2 pos = CalculatePosition(index); Vector2 pos = CalculatePosition(index);
Vector3 position = direction == Direction.Vertical ? new Vector3(pos.x - contentOffset.x, -pos.y + contentOffset.y, 0) : new Vector3(pos.x - contentOffset.x, -pos.y + contentOffset.y, 0); Vector3 position = direction == Direction.Vertical ?
new Vector3(pos.x - contentOffset.x, -pos.y + contentOffset.y, 0) :
new Vector3(pos.x - contentOffset.x, -pos.y + contentOffset.y, 0);
viewHolder.RectTransform.anchoredPosition3D = position; viewHolder.RectTransform.anchoredPosition3D = position;
} }
@ -155,9 +135,7 @@ namespace AlicizaX.UI
public abstract int PositionToIndex(float position); public abstract int PositionToIndex(float position);
public virtual void DoItemAnimation() public virtual void DoItemAnimation() { }
{
}
public virtual bool IsFullVisibleStart(int index) public virtual bool IsFullVisibleStart(int index)
{ {
@ -222,7 +200,6 @@ namespace AlicizaX.UI
{ {
len = alignment == Alignment.Center ? Mathf.Min(contentSize.x, viewportSize.x) : viewportSize.x; len = alignment == Alignment.Center ? Mathf.Min(contentSize.x, viewportSize.x) : viewportSize.x;
} }
return len; return len;
} }
@ -234,9 +211,9 @@ namespace AlicizaX.UI
public enum Direction public enum Direction
{ {
Vertical, Vertical = 0,
Horizontal, Horizontal = 1,
Custom, Custom = 2
} }
public enum Alignment public enum Alignment

View File

@ -1,14 +1,14 @@
using System;
using UnityEngine; using UnityEngine;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
[Serializable]
public class LinearLayoutManager : LayoutManager public class LinearLayoutManager : LayoutManager
{ {
protected float lineHeight; protected float lineHeight;
public LinearLayoutManager() public LinearLayoutManager() { }
{
}
public override Vector2 CalculateContentSize() public override Vector2 CalculateContentSize()
{ {
@ -22,7 +22,6 @@ namespace AlicizaX.UI
position = index * (lineHeight + spacing.y) - spacing.y; position = index * (lineHeight + spacing.y) - spacing.y;
return new Vector2(contentSize.x, position + padding.y * 2); return new Vector2(contentSize.x, position + padding.y * 2);
} }
position = index * (lineHeight + spacing.x) - spacing.x; position = index * (lineHeight + spacing.x) - spacing.x;
return new Vector2(position + padding.x * 2, contentSize.y); return new Vector2(position + padding.x * 2, contentSize.y);
} }
@ -35,7 +34,6 @@ namespace AlicizaX.UI
position = index * (lineHeight + spacing.y) - ScrollPosition; position = index * (lineHeight + spacing.y) - ScrollPosition;
return new Vector2(0, position + padding.y); return new Vector2(0, position + padding.y);
} }
position = index * (lineHeight + spacing.x) - ScrollPosition; position = index * (lineHeight + spacing.x) - ScrollPosition;
return new Vector2(position + padding.x, 0); return new Vector2(position + padding.x, 0);
} }
@ -47,7 +45,6 @@ namespace AlicizaX.UI
{ {
return new Vector2(0, (len - lineHeight) / 2); return new Vector2(0, (len - lineHeight) / 2);
} }
return new Vector2((len - lineHeight) / 2, 0); return new Vector2((len - lineHeight) / 2, 0);
} }
@ -57,7 +54,6 @@ namespace AlicizaX.UI
{ {
return new Vector2(0, (viewportSize.y - lineHeight) / 2); return new Vector2(0, (viewportSize.y - lineHeight) / 2);
} }
return new Vector2((viewportSize.x - lineHeight) / 2, 0); return new Vector2((viewportSize.x - lineHeight) / 2, 0);
} }

View File

@ -1,7 +1,9 @@
using System;
using UnityEngine; using UnityEngine;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
[Serializable]
public class MixedLayoutManager : LayoutManager public class MixedLayoutManager : LayoutManager
{ {
public MixedLayoutManager() { } public MixedLayoutManager() { }

View File

@ -4,10 +4,10 @@ using UnityEngine;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
[Serializable]
public class PageLayoutManager : LinearLayoutManager public class PageLayoutManager : LinearLayoutManager
{ {
[SerializeField] [SerializeField] private float minScale = 0.9f;
private float minScale;
public PageLayoutManager() public PageLayoutManager()
{ {

View File

@ -1,3 +1,8 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 3a9bb27da68d4451a7d79cdb7abc1506 guid: 3a9bb27da68d4451a7d79cdb7abc1506
timeCreated: 1748431180 folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,6 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
public interface IMixedObjectFactory<T> where T : class
internal interface IMixedObjectFactory<T> where T : class
{ {
T Create(string typeName); T Create(string typeName);
@ -12,5 +10,4 @@ namespace SimpleObjectPool
bool Validate(string typeName, T obj); bool Validate(string typeName, T obj);
} }
} }

View File

@ -1,8 +1,8 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
using System; using System;
internal interface IMixedObjectPool<T> : IDisposable where T : class public interface IMixedObjectPool<T> : IDisposable where T : class
{ {
T Allocate(string typeName); T Allocate(string typeName);

View File

@ -1,8 +1,6 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
public interface IObjectFactory<T> where T : class
internal interface IObjectFactory<T> where T : class
{ {
/// <summary> /// <summary>
/// 创建对象 /// 创建对象
@ -29,5 +27,4 @@ namespace SimpleObjectPool
/// <returns></returns> /// <returns></returns>
bool Validate(T obj); bool Validate(T obj);
} }
} }

View File

@ -1,8 +1,8 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
using System; using System;
internal interface IObjectPool : IDisposable public interface IObjectPool : IDisposable
{ {
/// <summary> /// <summary>
/// 从池子中分配一个可用对象,没有的话就创建一个 /// 从池子中分配一个可用对象,没有的话就创建一个
@ -17,7 +17,7 @@ namespace SimpleObjectPool
void Free(object obj); void Free(object obj);
} }
internal interface IObjectPool<T> : IObjectPool, IDisposable where T : class public interface IObjectPool<T> : IObjectPool, IDisposable where T : class
{ {
new T Allocate(); new T Allocate();

View File

@ -1,10 +1,7 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
public interface IPooledObject
internal interface IPooledObject
{ {
void Free(); void Free();
} }
} }

View File

@ -1,10 +1,10 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
internal class MixedObjectPool<T> : IMixedObjectPool<T> where T : class public class MixedObjectPool<T> : IMixedObjectPool<T> where T : class
{ {
private const int DEFAULT_MAX_SIZE_PER_TYPE = 10; private const int DEFAULT_MAX_SIZE_PER_TYPE = 10;

View File

@ -1,9 +1,9 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
using System; using System;
using System.Threading; using System.Threading;
internal class ObjectPool<T> : IObjectPool<T> where T : class public class ObjectPool<T> : IObjectPool<T> where T : class
{ {
private int maxSize; private int maxSize;
private int initialSize; private int initialSize;

View File

@ -1,8 +1,8 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
using UnityEngine; using UnityEngine;
internal class UnityComponentFactory<T> : IObjectFactory<T> where T : Component public class UnityComponentFactory<T> : IObjectFactory<T> where T : Component
{ {
private T template; private T template;
private Transform parent; private Transform parent;

View File

@ -1,8 +1,8 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
using UnityEngine; using UnityEngine;
internal class UnityGameObjectFactory : IObjectFactory<GameObject> public class UnityGameObjectFactory : IObjectFactory<GameObject>
{ {
protected GameObject template; protected GameObject template;
protected Transform parent; protected Transform parent;

View File

@ -1,10 +1,10 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
internal class UnityMixedComponentFactory<T> : IMixedObjectFactory<T> where T : Component public class UnityMixedComponentFactory<T> : IMixedObjectFactory<T> where T : Component
{ {
protected T template; protected T template;
protected Transform parent; protected Transform parent;

View File

@ -1,8 +1,8 @@
namespace SimpleObjectPool namespace AlicizaX.UI
{ {
using UnityEngine; using UnityEngine;
internal class UnityMixedGameObjectFactory : IMixedObjectFactory<GameObject> public class UnityMixedGameObjectFactory : IMixedObjectFactory<GameObject>
{ {
protected GameObject template; protected GameObject template;
protected Transform parent; protected Transform parent;
@ -40,5 +40,4 @@ namespace SimpleObjectPool
return true; return true;
} }
} }
} }

View File

@ -1,13 +1,61 @@
using System; using System;
using UnityEngine; using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI; using UnityEngine.UI;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
public class RecyclerView : MonoBehaviour public class RecyclerView : MonoBehaviour
{ {
[SerializeField] private Direction direction; #region Serialized Fields - Layout Settings
[HideInInspector] [SerializeField] private Direction direction;
[HideInInspector] [SerializeField] private Alignment alignment;
[HideInInspector] [SerializeField] private Vector2 spacing;
[HideInInspector] [SerializeField] private Vector2 padding;
#endregion
#region Serialized Fields - Scroll Settings
[HideInInspector] [SerializeField] private bool scroll;
[HideInInspector] [SerializeField] private bool snap;
[HideInInspector] [SerializeField, Range(1f, 50f)]
private float scrollSpeed = 7f;
[HideInInspector] [SerializeField, Range(10f, 50f)]
private float wheelSpeed = 30f;
#endregion
#region Serialized Fields - Components
[HideInInspector] [SerializeField] private ViewHolder[] templates;
[HideInInspector] [SerializeField] private RectTransform content;
[HideInInspector] [SerializeField] private bool showScrollBar;
[HideInInspector] [SerializeField] private Scrollbar scrollbar;
#endregion
#region Serialized Fields - Internal (Hidden in Inspector)
[HideInInspector] [SerializeField] private string _layoutManagerTypeName;
[SerializeReference] private LayoutManager layoutManager;
[HideInInspector] [SerializeField] private string _scrollerTypeName;
[HideInInspector] [SerializeReference] private Scroller scroller;
#endregion
#region Private Fields
private ViewProvider viewProvider;
private int startIndex;
private int endIndex;
private int currentIndex;
#endregion
#region Public Properties - Layout Settings
public Direction Direction public Direction Direction
{ {
@ -15,15 +63,119 @@ namespace AlicizaX.UI
set => direction = value; set => direction = value;
} }
[SerializeField] private Alignment alignment;
public Alignment Alignment public Alignment Alignment
{ {
get => alignment; get => alignment;
set => alignment = value; set => alignment = value;
} }
[SerializeField] private RectTransform content; public Vector2 Spacing
{
get => spacing;
set => spacing = value;
}
public Vector2 Padding
{
get => padding;
set => padding = value;
}
#endregion
#region Public Properties - Scroll Settings
public bool Scroll
{
get => scroll;
set
{
if (scroll == value) return;
scroll = value;
// 启/停 scroller如果存在
if (scroller != null)
{
// 如果 Scroller 是 MonoBehaviour可以启/停组件;否则回退到设置一个 Position/flags
scroller.enabled = scroll;
// 将当前的滚动相关配置下发到 scroller保持一致性
scroller.ScrollSpeed = scrollSpeed;
scroller.WheelSpeed = wheelSpeed;
scroller.Snap = snap;
}
// 更新 scrollbar 显示(只有在 showScrollBar 为 true 时才显示)
if (scrollbar != null)
{
scrollbar.gameObject.SetActive(showScrollBar && scroll);
}
// 如果启用/禁用滚动后需要调整布局或滚动条大小,刷新布局
RequestLayout();
}
}
public bool Snap
{
get => snap;
set
{
// Snap 依赖于 Scroll与原逻辑保持一致
bool newSnap = value & scroll;
if (snap == newSnap) return;
snap = newSnap;
if (scroller != null)
{
scroller.Snap = snap;
}
// 如果开启了 snap可以选做立即对齐到最近项
// if (snap && scroller != null) SnapToNearestItem();
}
}
public float ScrollSpeed
{
get => scrollSpeed;
set
{
if (Mathf.Approximately(scrollSpeed, value)) return;
scrollSpeed = value;
if (scroller != null)
{
scroller.ScrollSpeed = scrollSpeed;
}
}
}
public float WheelSpeed
{
get => wheelSpeed;
set
{
if (Mathf.Approximately(wheelSpeed, value)) return;
wheelSpeed = value;
if (scroller != null)
{
scroller.WheelSpeed = wheelSpeed;
}
}
}
#endregion
#region Public Properties - Components
public ViewHolder[] Templates
{
get => templates;
set => templates = value;
}
public RectTransform Content public RectTransform Content
{ {
@ -38,328 +190,354 @@ namespace AlicizaX.UI
} }
} }
[SerializeField] private Vector2 spacing; public Scrollbar Scrollbar => scrollbar;
public Vector2 Spacing
{
get => spacing;
set => spacing = value;
}
[SerializeField] private Vector2 padding;
public Vector2 Padding
{
get => padding;
set => padding = value;
}
[SerializeField] private bool scroll;
public bool Scroll
{
get => scroll;
set => scroll = value;
}
[SerializeField] private bool snap;
public bool Snap
{
get => snap;
set => snap = value & scroll;
}
[SerializeField, Range(1f, 50f)] private float scrollSpeed = 7f;
public float ScrollSpeed
{
get => scrollSpeed;
set => scrollSpeed = value;
}
[SerializeField, Range(10f, 50f)] private float wheelSpeed = 30f;
public float WheeelSpeed
{
get => wheelSpeed;
set => wheelSpeed = value;
}
[SerializeField] private ViewHolder[] templates;
public ViewHolder[] Templates
{
get => templates;
}
[SerializeField] private string _scrollerTypeName;
[SerializeReference] private Scroller _scroller;
[SerializeField] private bool _showScrollBar;
[SerializeReference] private Scrollbar _scrollbar;
private ViewProvider viewProvider;
[SerializeField] private string _layoutManagerTypeName;
[SerializeReference] private LayoutManager _layoutManager;
private int startIndex, endIndex;
private int currentIndex;
public Scroller Scroller => _scroller;
public int CurrentIndex
{
get => currentIndex;
}
public bool CanScroll => true;
public Scroller Scroller => scroller;
public ViewProvider ViewProvider public ViewProvider ViewProvider
{ {
get get
{ {
viewProvider ??= templates.Length > 1 ? new MixedViewProvider(this, templates) : new SimpleViewProvider(this, templates); if (viewProvider == null)
{
viewProvider = templates.Length > 1
? new MixedViewProvider(this, templates)
: new SimpleViewProvider(this, templates);
}
return viewProvider; return viewProvider;
} }
} }
public Scrollbar Scrollbar => _scrollbar; #endregion
private IAdapter _adapter; #region Public Properties - State
public IAdapter RecyclerViewAdapter { get; set; }
public int CurrentIndex
{
get => currentIndex;
set => currentIndex = value;
}
#endregion
#region Events
public Action<int> OnIndexChanged; public Action<int> OnIndexChanged;
public Action OnScrollValueChanged; public Action OnScrollValueChanged;
public Action OnMoveingChanged;
private void OnValidate() #endregion
{
if (_scroller != null)
{
_scroller.ScrollSpeed = scrollSpeed;
_scroller.WheelSpeed = wheelSpeed;
}
}
private void OnScrollChanged(float pos) #region Unity Lifecycle
{
_layoutManager.UpdateLayout();
if (Scrollbar != null)
{
Scrollbar.SetValueWithoutNotify(pos / _scroller.MaxPosition);
}
if (_layoutManager.IsFullInvisibleStart(startIndex))
{
viewProvider.RemoveViewHolder(startIndex);
startIndex += _layoutManager.Unit;
}
else if (_layoutManager.IsFullVisibleStart(startIndex))
{
if (startIndex == 0)
{
// TODO Do something, eg: Refresh
}
else
{
startIndex -= _layoutManager.Unit;
viewProvider.CreateViewHolder(startIndex);
}
}
if (_layoutManager.IsFullInvisibleEnd(endIndex))
{
viewProvider.RemoveViewHolder(endIndex);
endIndex -= _layoutManager.Unit;
}
else if (_layoutManager.IsFullVisibleEnd(endIndex))
{
if (endIndex >= viewProvider.GetItemCount() - _layoutManager.Unit)
{
// TODO Do something, eg: Load More
}
else
{
endIndex += _layoutManager.Unit;
viewProvider.CreateViewHolder(endIndex);
}
}
// 使用滚动条快速定位时,刷新整个列表
if (!_layoutManager.IsVisible(startIndex) || !_layoutManager.IsVisible(endIndex))
{
Refresh();
}
_layoutManager.DoItemAnimation();
OnScrollValueChanged?.Invoke();
}
private void OnMoveing()
{
OnMoveingChanged?.Invoke();
}
private void OnMoveStoped()
{
if (Snap)
{
SnapTo();
}
}
private void OnScrollbarChanged(float ratio)
{
_scroller.ScrollToRatio(ratio);
}
private void OnScrollbarDragEnd()
{
if (_scroller.Position < _scroller.MaxPosition)
{
if (Snap)
{
SnapTo();
}
}
}
private void Awake() private void Awake()
{ {
InitializeTemplates();
ConfigureScroller();
ConfigureScrollbar();
}
#endregion
#region Initialization
private void InitializeTemplates()
{
if (templates == null) return;
for (int i = 0; i < templates.Length; i++) for (int i = 0; i < templates.Length; i++)
{
if (templates[i] != null)
{ {
templates[i].gameObject.SetActive(false); templates[i].gameObject.SetActive(false);
} }
}
ConfigScroller();
ConfigScrollbar();
} }
private void OnDestroy() private void ConfigureScroller()
{ {
viewProvider?.Dispose(); if (scroller == null) return;
scroller.ScrollSpeed = scrollSpeed;
scroller.WheelSpeed = wheelSpeed;
scroller.Snap = snap;
scroller.OnValueChanged.AddListener(OnScrollChanged);
scroller.OnMoveStoped.AddListener(OnMoveStoped);
}
private void ConfigureScrollbar()
{
if (!showScrollBar || scrollbar == null) return;
scrollbar.gameObject.SetActive(scroll);
scrollbar.onValueChanged.AddListener(OnScrollbarChanged);
var scrollbarEx = scrollbar.gameObject.GetComponent<ScrollbarEx>();
if (scrollbarEx == null)
{
scrollbarEx = scrollbar.gameObject.AddComponent<ScrollbarEx>();
}
scrollbarEx.OnDragEnd = OnScrollbarDragEnd;
}
#endregion
#region Public Methods - Setup
public void SetAdapter(IAdapter adapter)
{
if (adapter == null)
{
Debug.LogError("Adapter cannot be null");
return;
}
RecyclerViewAdapter = adapter;
ViewProvider.Adapter = adapter;
ViewProvider.LayoutManager = layoutManager;
layoutManager.RecyclerView = this;
layoutManager.Adapter = adapter;
layoutManager.ViewProvider = viewProvider;
layoutManager.Direction = direction;
layoutManager.Alignment = alignment;
layoutManager.Spacing = spacing;
layoutManager.Padding = padding;
} }
public void Reset() public void Reset()
{ {
viewProvider?.Reset(); viewProvider?.Reset();
if (_scroller != null)
if (scroller != null)
{ {
_scroller.Position = 0; scroller.Position = 0;
} }
if (_scrollbar != null) if (scrollbar != null)
{ {
_scrollbar.SetValueWithoutNotify(0); scrollbar.SetValueWithoutNotify(0);
} }
} }
public void SetAdapter(IAdapter adapter) #endregion
{
_adapter = adapter;
ViewProvider.Adapter = _adapter;
ViewProvider.LayoutManager = _layoutManager;
_layoutManager.RecyclerView = this;
_layoutManager.Adapter = _adapter;
_layoutManager.ViewProvider = viewProvider;
_layoutManager.Direction = direction;
_layoutManager.Alignment = alignment;
_layoutManager.Spacing = spacing;
_layoutManager.Padding = padding;
_layoutManager.CanScroll = CanScroll;
}
#region Public Methods - Layout
private void ConfigScroller()
{
if (_scroller != null)
{
_scroller.ScrollSpeed = scrollSpeed;
_scroller.WheelSpeed = wheelSpeed;
_scroller.Snap = Snap;
_scroller.OnValueChanged.AddListener(OnScrollChanged);
_scroller.OnMoveStoped.AddListener(OnMoveStoped);
_scroller.OnMoveing.AddListener(OnMoveing);
}
}
private void ConfigScrollbar()
{
if (_showScrollBar && _scrollbar != null)
{
_scrollbar.gameObject.SetActive(scroll);
_scrollbar.onValueChanged.AddListener(OnScrollbarChanged);
_scrollbar.gameObject.AddComponent<ScrollbarEx>().OnDragEnd = OnScrollbarDragEnd;
}
}
public void Refresh() public void Refresh()
{ {
ViewProvider.Clear(); ViewProvider.Clear();
startIndex = _layoutManager.GetStartIndex(); startIndex = layoutManager.GetStartIndex();
endIndex = _layoutManager.GetEndIndex(); endIndex = layoutManager.GetEndIndex();
for (int i = startIndex; i <= endIndex; i += _layoutManager.Unit)
for (int i = startIndex; i <= endIndex; i += layoutManager.Unit)
{ {
ViewProvider.CreateViewHolder(i); ViewProvider.CreateViewHolder(i);
} }
_layoutManager.DoItemAnimation(); layoutManager.DoItemAnimation();
} }
public void RequestLayout() public void RequestLayout()
{ {
_layoutManager.SetContentSize(); layoutManager.SetContentSize();
if (_scroller == null) return; if (scroller == null) return;
_scroller.Direction = direction; scroller.Direction = direction;
_scroller.ViewSize = _layoutManager.ViewportSize; scroller.ViewSize = layoutManager.ViewportSize;
_scroller.ContentSize = _layoutManager.ContentSize; scroller.ContentSize = layoutManager.ContentSize;
if (Scrollbar != null && _scroller.ContentSize != Vector2.zero) UpdateScrollbarVisibility();
{
if ((direction == Direction.Vertical && _layoutManager.ContentSize.y <= _layoutManager.ViewportSize.y) ||
(direction == Direction.Horizontal && _layoutManager.ContentSize.x <= _layoutManager.ViewportSize.x) ||
(direction == Direction.Custom))
{
Scrollbar.gameObject.SetActive(false);
}
else
{
Scrollbar.gameObject.SetActive(true);
Scrollbar.direction = direction == Direction.Vertical ? Scrollbar.Direction.TopToBottom : Scrollbar.Direction.LeftToRight;
Scrollbar.size = direction == Direction.Vertical ? _scroller.ViewSize.y / _scroller.ContentSize.y : _scroller.ViewSize.x / _scroller.ContentSize.x;
}
}
} }
#endregion
#region Public Methods - Scrolling
public float GetScrollPosition() public float GetScrollPosition()
{ {
return _scroller ? _scroller.Position : 0; return scroller != null ? scroller.Position : 0;
} }
public void ScrollTo(int index, bool smooth = false) public void ScrollTo(int index, bool smooth = false)
{ {
if (!scroll) return; if (!scroll || scroller == null) return;
scroller.ScrollTo(layoutManager.IndexToPosition(index), smooth);
_scroller.ScrollTo(_layoutManager.IndexToPosition(index), smooth);
if (!smooth) if (!smooth)
{ {
Refresh(); Refresh();
} }
index %= _adapter.GetItemCount(); UpdateCurrentIndex(index);
index = index < 0 ? _adapter.GetItemCount() + index : index; }
#endregion
#region Private Methods - Scroll Callbacks
private void OnScrollChanged(float position)
{
layoutManager.UpdateLayout();
UpdateScrollbarValue(position);
UpdateVisibleRange();
layoutManager.DoItemAnimation();
OnScrollValueChanged?.Invoke();
}
private void OnMoveStoped()
{
if (snap)
{
SnapToNearestItem();
}
}
private void OnScrollbarChanged(float ratio)
{
if (scroller != null)
{
scroller.ScrollToRatio(ratio);
}
}
private void OnScrollbarDragEnd()
{
if (scroller == null) return;
if (scroller.Position < scroller.MaxPosition && snap)
{
SnapToNearestItem();
}
}
#endregion
#region Private Methods - Scroll Helpers
private void UpdateScrollbarValue(float position)
{
if (scrollbar != null && scroller != null)
{
float ratio = scroller.MaxPosition > 0 ? position / scroller.MaxPosition : 0;
scrollbar.SetValueWithoutNotify(ratio);
}
}
private void UpdateVisibleRange()
{
// Handle start index
if (layoutManager.IsFullInvisibleStart(startIndex))
{
viewProvider.RemoveViewHolder(startIndex);
startIndex += layoutManager.Unit;
}
else if (layoutManager.IsFullVisibleStart(startIndex))
{
if (startIndex == 0)
{
// TODO: Implement refresh logic
}
else
{
startIndex -= layoutManager.Unit;
viewProvider.CreateViewHolder(startIndex);
}
}
// Handle end index
if (layoutManager.IsFullInvisibleEnd(endIndex))
{
viewProvider.RemoveViewHolder(endIndex);
endIndex -= layoutManager.Unit;
}
else if (layoutManager.IsFullVisibleEnd(endIndex))
{
if (endIndex >= viewProvider.GetItemCount() - layoutManager.Unit)
{
// TODO: Implement load more logic
}
else
{
endIndex += layoutManager.Unit;
viewProvider.CreateViewHolder(endIndex);
}
}
// Refresh if out of visible range
if (!layoutManager.IsVisible(startIndex) || !layoutManager.IsVisible(endIndex))
{
Refresh();
}
}
private void UpdateScrollbarVisibility()
{
if (scrollbar == null || scroller == null || layoutManager.ContentSize == Vector2.zero)
return;
bool shouldShow = ShouldShowScrollbar();
scrollbar.gameObject.SetActive(shouldShow);
if (shouldShow)
{
ConfigureScrollbarDirection();
ConfigureScrollbarSize();
}
}
private bool ShouldShowScrollbar()
{
if (direction == Direction.Custom) return false;
if (direction == Direction.Vertical)
{
return layoutManager.ContentSize.y > layoutManager.ViewportSize.y;
}
else // Horizontal
{
return layoutManager.ContentSize.x > layoutManager.ViewportSize.x;
}
}
private void ConfigureScrollbarDirection()
{
scrollbar.direction = direction == Direction.Vertical
? Scrollbar.Direction.TopToBottom
: Scrollbar.Direction.LeftToRight;
}
private void ConfigureScrollbarSize()
{
if (direction == Direction.Vertical)
{
scrollbar.size = scroller.ViewSize.y / scroller.ContentSize.y;
}
else
{
scrollbar.size = scroller.ViewSize.x / scroller.ContentSize.x;
}
}
private void SnapToNearestItem()
{
int index = layoutManager.PositionToIndex(GetScrollPosition());
ScrollTo(index, true);
}
private void UpdateCurrentIndex(int index)
{
if (RecyclerViewAdapter == null) return;
int itemCount = RecyclerViewAdapter.GetItemCount();
index %= itemCount;
index = index < 0 ? itemCount + index : index;
if (currentIndex != index) if (currentIndex != index)
{ {
@ -368,11 +546,6 @@ namespace AlicizaX.UI
} }
} }
#endregion
private void SnapTo()
{
var index = _layoutManager.PositionToIndex(GetScrollPosition());
ScrollTo(index, true);
}
} }
} }

View File

@ -5,7 +5,7 @@ MonoImporter:
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {fileID: 2800000, guid: a01ce47da31a2e0438fd8d38b203c0d5, type: 3} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:

View File

@ -1,10 +1,8 @@
using System;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
[Serializable]
public class CircleScroller : Scroller public class CircleScroller : Scroller
{ {
private Vector2 centerPosition; private Vector2 centerPosition;

View File

@ -9,19 +9,7 @@ namespace AlicizaX.UI
void ScrollTo(float position, bool smooth = false); void ScrollTo(float position, bool smooth = false);
} }
public class ScrollerEvent : UnityEvent<float> public class ScrollerEvent : UnityEvent<float> { }
{ public class MoveStopEvent : UnityEvent { }
} public class DraggingEvent : UnityEvent<bool> { }
public class MoveStopEvent : UnityEvent
{
}
public class DraggingEvent : UnityEvent<bool>
{
}
public class MoveingEvent : UnityEvent
{
}
} }

View File

@ -1,26 +1,18 @@
using System;
using System.Collections; using System.Collections;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {
[Serializable]
public class Scroller : MonoBehaviour, IScroller, IBeginDragHandler, IEndDragHandler, IDragHandler, IScrollHandler public class Scroller : MonoBehaviour, IScroller, IBeginDragHandler, IEndDragHandler, IDragHandler, IScrollHandler
{ {
protected float position; protected float position;
public float Position { get => position; set => position = value; }
public float Position
{
get => position;
set => position = value;
}
protected float velocity; protected float velocity;
public float Velocity => velocity; public float Velocity => velocity;
protected Direction direction; protected Direction direction;
public Direction Direction public Direction Direction
{ {
get => direction; get => direction;
@ -31,7 +23,6 @@ namespace AlicizaX.UI
/// 内容所需要大小 /// 内容所需要大小
/// </summary> /// </summary>
protected Vector2 contentSize; protected Vector2 contentSize;
public Vector2 ContentSize public Vector2 ContentSize
{ {
get => contentSize; get => contentSize;
@ -42,7 +33,6 @@ namespace AlicizaX.UI
/// 所在 View 的真实大小 /// 所在 View 的真实大小
/// </summary> /// </summary>
protected Vector2 viewSize; protected Vector2 viewSize;
public Vector2 ViewSize public Vector2 ViewSize
{ {
get => viewSize; get => viewSize;
@ -50,7 +40,6 @@ namespace AlicizaX.UI
} }
protected float scrollSpeed = 1f; protected float scrollSpeed = 1f;
public float ScrollSpeed public float ScrollSpeed
{ {
get => scrollSpeed; get => scrollSpeed;
@ -58,7 +47,6 @@ namespace AlicizaX.UI
} }
protected float wheelSpeed = 30f; protected float wheelSpeed = 30f;
public float WheelSpeed public float WheelSpeed
{ {
get => wheelSpeed; get => wheelSpeed;
@ -66,7 +54,6 @@ namespace AlicizaX.UI
} }
protected bool snap; protected bool snap;
public bool Snap public bool Snap
{ {
get => snap; get => snap;
@ -76,38 +63,21 @@ namespace AlicizaX.UI
protected ScrollerEvent scrollerEvent = new(); protected ScrollerEvent scrollerEvent = new();
protected MoveStopEvent moveStopEvent = new(); protected MoveStopEvent moveStopEvent = new();
protected DraggingEvent draggingEvent = new(); protected DraggingEvent draggingEvent = new();
protected MoveingEvent moveingEvent = new();
public float MaxPosition => direction == Direction.Vertical ? Mathf.Max(contentSize.y - viewSize.y, 0) : Mathf.Max(contentSize.x - viewSize.x, 0); public float MaxPosition => direction == Direction.Vertical ?
Mathf.Max(contentSize.y - viewSize.y, 0) :
Mathf.Max(contentSize.x - viewSize.x, 0);
public float ViewLength => direction == Direction.Vertical ? viewSize.y : viewSize.x; public float ViewLength => direction == Direction.Vertical ? viewSize.y : viewSize.x;
public MoveingEvent OnMoveing public ScrollerEvent OnValueChanged { get => scrollerEvent; set => scrollerEvent = value; }
{
get => moveingEvent;
set => moveingEvent = value;
}
public ScrollerEvent OnValueChanged public MoveStopEvent OnMoveStoped { get => moveStopEvent; set => moveStopEvent = value; }
{
get => scrollerEvent;
set => scrollerEvent = value;
}
public MoveStopEvent OnMoveStoped public DraggingEvent OnDragging { get => draggingEvent; set => draggingEvent = value; }
{
get => moveStopEvent;
set => moveStopEvent = value;
}
public DraggingEvent OnDragging
{
get => draggingEvent;
set => draggingEvent = value;
}
// 停止滑动的时间,但此时并未释放鼠标按键 // 停止滑动的时间,但此时并未释放鼠标按键
private float dragStopTime = 0f; public float dragStopTime = 0f;
public virtual void ScrollTo(float position, bool smooth = false) public virtual void ScrollTo(float position, bool smooth = false)
{ {
@ -151,10 +121,9 @@ namespace AlicizaX.UI
position += velocity; position += velocity;
OnValueChanged?.Invoke(position); OnValueChanged?.Invoke(position);
OnMoveing?.Invoke();
} }
public virtual void OnScrolled(PointerEventData eventData) public void OnScroll(PointerEventData eventData)
{ {
StopAllCoroutines(); StopAllCoroutines();
@ -163,7 +132,7 @@ namespace AlicizaX.UI
position += velocity; position += velocity;
OnValueChanged?.Invoke(position); OnValueChanged?.Invoke(position);
OnMoveing?.Invoke(); Inertia();
Elastic(); Elastic();
} }
@ -184,7 +153,6 @@ namespace AlicizaX.UI
{ {
rate = Mathf.Max(0, 1 - (Mathf.Abs(position - MaxPosition) / ViewLength)); rate = Mathf.Max(0, 1 - (Mathf.Abs(position - MaxPosition) / ViewLength));
} }
return rate; return rate;
} }
@ -273,11 +241,5 @@ namespace AlicizaX.UI
position = targetPos; position = targetPos;
OnValueChanged?.Invoke(position); OnValueChanged?.Invoke(position);
} }
void IScrollHandler.OnScroll(PointerEventData eventData)
{
OnScrolled(eventData);
}
} }
} }

View File

@ -74,7 +74,7 @@ namespace AlicizaX.UI
} }
} }
public static class UGList public static class UGListCreateHelper
{ {
public static UGList<TData> Create<TData>(RecyclerView recyclerView, Action<TData> onItemClick = null) where TData : ISimpleViewData public static UGList<TData> Create<TData>(RecyclerView recyclerView, Action<TData> onItemClick = null) where TData : ISimpleViewData
=> new UGList<TData>(recyclerView, onItemClick); => new UGList<TData>(recyclerView, onItemClick);

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fd094e3cb2194cb193221ea9436a169a
timeCreated: 1766729620

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 369d2829a7a2462ba93212b3d8afe0fa
timeCreated: 1763615925

View File

@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 19892a10438348b3b7e7cac3e2201b9e
timeCreated: 1763615934

View File

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using SimpleObjectPool;
using UnityEngine; using UnityEngine;
namespace AlicizaX.UI namespace AlicizaX.UI

View File

@ -1,5 +1,4 @@
using System; using System;
using SimpleObjectPool;
namespace AlicizaX.UI namespace AlicizaX.UI
{ {

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using AlicizaX.UI.Runtime;
using UnityEngine; using UnityEngine;
namespace AlicizaX.UI namespace AlicizaX.UI
@ -8,7 +6,7 @@ namespace AlicizaX.UI
/// <summary> /// <summary>
/// 提供和管理 ViewHolder /// 提供和管理 ViewHolder
/// </summary> /// </summary>
public abstract class ViewProvider : IDisposable public abstract class ViewProvider
{ {
private readonly List<ViewHolder> viewHolders = new(); private readonly List<ViewHolder> viewHolders = new();
@ -44,10 +42,10 @@ namespace AlicizaX.UI
string viewName = Adapter.GetViewName(i); string viewName = Adapter.GetViewName(i);
var viewHolder = Allocate(viewName); var viewHolder = Allocate(viewName);
viewHolder.OnStart();
viewHolder.Name = viewName; viewHolder.Name = viewName;
viewHolder.Index = i; viewHolder.Index = i;
viewHolders.Add(viewHolder); viewHolders.Add(viewHolder);
LayoutManager.Layout(viewHolder, i); LayoutManager.Layout(viewHolder, i);
Adapter.OnBindViewHolder(viewHolder, i); Adapter.OnBindViewHolder(viewHolder, i);
} }
@ -131,15 +129,5 @@ namespace AlicizaX.UI
{ {
return Adapter == null ? 0 : Adapter.GetItemCount(); return Adapter == null ? 0 : Adapter.GetItemCount();
} }
public void Dispose()
{
foreach (var viewHolder in viewHolders)
{
Free(viewHolder.Name, viewHolder);
}
viewHolders.Clear();
}
} }
} }