修改
This commit is contained in:
parent
fc993a1dbe
commit
26c205ddc0
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@ GameObject:
|
||||
- component: {fileID: 409256563818501030}
|
||||
- component: {fileID: 4967247000384896254}
|
||||
- component: {fileID: 2527097672867102998}
|
||||
- component: {fileID: 144409482669617178}
|
||||
- component: {fileID: 222070472718835377}
|
||||
m_Layer: 5
|
||||
m_Name: ScrollView
|
||||
m_TagString: Untagged
|
||||
@ -90,9 +90,8 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 7efd8e83d2092b347952108134dc37eb, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
direction: 1
|
||||
direction: 0
|
||||
alignment: 1
|
||||
content: {fileID: 7227160576944475251}
|
||||
spacing: {x: 0, y: 0}
|
||||
padding: {x: 0, y: 0}
|
||||
scroll: 1
|
||||
@ -100,20 +99,21 @@ MonoBehaviour:
|
||||
scrollSpeed: 10
|
||||
wheelSpeed: 30
|
||||
templates: []
|
||||
_scrollerTypeName: AlicizaX.UI.RecyclerView.Scroller
|
||||
_scroller: {fileID: 144409482669617178}
|
||||
_showScrollBar: 0
|
||||
_scrollbar: {fileID: 0}
|
||||
content: {fileID: 7227160576944475251}
|
||||
showScrollBar: 0
|
||||
scrollbar: {fileID: 0}
|
||||
_layoutManagerTypeName: AlicizaX.UI.LinearLayoutManager
|
||||
_layoutManager:
|
||||
rid: 7492395943315111994
|
||||
layoutManager:
|
||||
rid: 6739296571988901898
|
||||
_scrollerTypeName: AlicizaX.UI.Scroller
|
||||
scroller: {fileID: 222070472718835377}
|
||||
references:
|
||||
version: 2
|
||||
RefIds:
|
||||
- rid: 7492395943315111994
|
||||
- rid: 6739296571988901898
|
||||
type: {class: LinearLayoutManager, ns: AlicizaX.UI, asm: AlicizaX.UI.Extension}
|
||||
data:
|
||||
--- !u!114 &144409482669617178
|
||||
--- !u!114 &222070472718835377
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
@ -125,6 +125,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 7b7de4cb3a1546e4a9ade6b8dbf8af92, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
dragStopTime: 0
|
||||
--- !u!1 &9220717789715235424
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
|
||||
@ -69,7 +69,7 @@ namespace AlicizaX.UI
|
||||
recyclerView.Refresh();
|
||||
}
|
||||
|
||||
protected internal virtual void SetList(List<T> list)
|
||||
public virtual void SetList(List<T> list)
|
||||
{
|
||||
this.list = list;
|
||||
recyclerView.Reset();
|
||||
|
||||
@ -87,7 +87,7 @@ namespace AlicizaX.UI
|
||||
base.NotifyDataChanged();
|
||||
}
|
||||
|
||||
protected internal override void SetList(List<TData> list)
|
||||
public override void SetList(List<TData> list)
|
||||
{
|
||||
showList.Clear();
|
||||
base.SetList(list);
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05736c35a54b467a966b416c1461ba61
|
||||
timeCreated: 1763617414
|
||||
guid: d43a3e6aece04b86ab8eb139abb89e46
|
||||
timeCreated: 1766661642
|
||||
@ -1,3 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a059b7119e284e37a88a569f76b40579
|
||||
timeCreated: 1763617420
|
||||
guid: cacaed2312884ce9ba739399b8271b93
|
||||
timeCreated: 1766661647
|
||||
@ -1,3 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d42e2db77425447490cb9f68003e818b
|
||||
timeCreated: 1741771999
|
||||
guid: fdf59811e23f47f19be6398684473df2
|
||||
timeCreated: 1766647995
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5cb3f76e0f84a7aa75959e194f524b5
|
||||
timeCreated: 1748588163
|
||||
@ -3,23 +3,20 @@ using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
[System.Serializable]
|
||||
public class CircleLayoutManager : LayoutManager
|
||||
{
|
||||
private float radius;
|
||||
private float intervalAngle;
|
||||
|
||||
private new CircleDirection direction;
|
||||
[SerializeField]
|
||||
private CircleDirection circleDirection= CircleDirection.Positive;
|
||||
[SerializeField]
|
||||
private float intervalAngle=0;
|
||||
|
||||
private float radius;
|
||||
private float initalAngle;
|
||||
|
||||
|
||||
public CircleLayoutManager(CircleDirection direction = CircleDirection.Positive)
|
||||
{
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public CircleLayoutManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override Vector2 CalculateContentSize()
|
||||
@ -49,7 +46,7 @@ namespace AlicizaX.UI
|
||||
public override Vector2 CalculatePosition(int index)
|
||||
{
|
||||
float angle = index * intervalAngle;
|
||||
angle = direction == CircleDirection.Positive ? angle : -angle;
|
||||
angle = circleDirection == CircleDirection.Positive ? angle : -angle;
|
||||
angle += initalAngle + ScrollPosition;
|
||||
float radian = angle * (Mathf.PI / 180f);
|
||||
float x = radius * Mathf.Sin(radian);
|
||||
@ -97,7 +94,7 @@ namespace AlicizaX.UI
|
||||
for (int i = 0; i < viewHolders.Count; i++)
|
||||
{
|
||||
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;
|
||||
delta = delta < 0 ? delta + 360 : delta;
|
||||
delta = delta > 180 ? 360 - delta : delta;
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
[Serializable]
|
||||
[System.Serializable]
|
||||
public class GridLayoutManager : LayoutManager
|
||||
{
|
||||
private Vector2 cellSize;
|
||||
|
||||
[SerializeField] private int cellCount;
|
||||
[SerializeField] private int cellCounnt = 1;
|
||||
|
||||
public GridLayoutManager()
|
||||
{
|
||||
unit = cellCount;
|
||||
this.unit = cellCounnt;
|
||||
}
|
||||
|
||||
public override Vector2 CalculateContentSize()
|
||||
@ -63,7 +62,6 @@ namespace AlicizaX.UI
|
||||
width = viewportSize.x;
|
||||
height = viewportSize.y;
|
||||
}
|
||||
|
||||
return new Vector2((width - cellSize.x) / 2, (height - cellSize.y) / 2);
|
||||
}
|
||||
|
||||
@ -80,7 +78,6 @@ namespace AlicizaX.UI
|
||||
width = viewportSize.x;
|
||||
height = viewportSize.y;
|
||||
}
|
||||
|
||||
return new Vector2((width - cellSize.x) / 2, (height - cellSize.y) / 2);
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
[Serializable]
|
||||
[System.Serializable]
|
||||
public abstract class LayoutManager : ILayoutManager
|
||||
{
|
||||
protected Vector2 viewportSize;
|
||||
|
||||
public Vector2 ViewportSize
|
||||
{
|
||||
get => viewportSize;
|
||||
@ -15,7 +13,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected Vector2 contentSize;
|
||||
|
||||
public Vector2 ContentSize
|
||||
{
|
||||
get => contentSize;
|
||||
@ -23,7 +20,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected Vector2 contentOffset;
|
||||
|
||||
public Vector2 ContentOffset
|
||||
{
|
||||
get => contentOffset;
|
||||
@ -31,7 +27,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected Vector2 viewportOffset;
|
||||
|
||||
public Vector2 ViewportOffset
|
||||
{
|
||||
get => viewportOffset;
|
||||
@ -39,7 +34,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected IAdapter adapter;
|
||||
|
||||
public IAdapter Adapter
|
||||
{
|
||||
get => adapter;
|
||||
@ -47,7 +41,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected ViewProvider viewProvider;
|
||||
|
||||
public ViewProvider ViewProvider
|
||||
{
|
||||
get => viewProvider;
|
||||
@ -55,7 +48,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected RecyclerView recyclerView;
|
||||
|
||||
public virtual RecyclerView RecyclerView
|
||||
{
|
||||
get => recyclerView;
|
||||
@ -63,7 +55,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected Direction direction;
|
||||
|
||||
public Direction Direction
|
||||
{
|
||||
get => direction;
|
||||
@ -71,7 +62,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected Alignment alignment;
|
||||
|
||||
public Alignment Alignment
|
||||
{
|
||||
get => alignment;
|
||||
@ -79,7 +69,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected Vector2 spacing;
|
||||
|
||||
public Vector2 Spacing
|
||||
{
|
||||
get => spacing;
|
||||
@ -87,7 +76,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected Vector2 padding;
|
||||
|
||||
public Vector2 Padding
|
||||
{
|
||||
get => padding;
|
||||
@ -95,26 +83,16 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected int unit = 1;
|
||||
|
||||
public int Unit
|
||||
{
|
||||
get => unit;
|
||||
set => unit = value;
|
||||
}
|
||||
|
||||
protected bool canScroll;
|
||||
|
||||
public bool CanScroll
|
||||
{
|
||||
get => canScroll;
|
||||
set => canScroll = value;
|
||||
}
|
||||
|
||||
public float ScrollPosition => recyclerView.GetScrollPosition();
|
||||
|
||||
public LayoutManager()
|
||||
{
|
||||
}
|
||||
public LayoutManager() { }
|
||||
|
||||
public void SetContentSize()
|
||||
{
|
||||
@ -135,7 +113,9 @@ namespace AlicizaX.UI
|
||||
public virtual void Layout(ViewHolder viewHolder, int 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;
|
||||
}
|
||||
|
||||
@ -155,9 +135,7 @@ namespace AlicizaX.UI
|
||||
|
||||
public abstract int PositionToIndex(float position);
|
||||
|
||||
public virtual void DoItemAnimation()
|
||||
{
|
||||
}
|
||||
public virtual void DoItemAnimation() { }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -234,9 +211,9 @@ namespace AlicizaX.UI
|
||||
|
||||
public enum Direction
|
||||
{
|
||||
Vertical,
|
||||
Horizontal,
|
||||
Custom,
|
||||
Vertical = 0,
|
||||
Horizontal = 1,
|
||||
Custom = 2
|
||||
}
|
||||
|
||||
public enum Alignment
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
[Serializable]
|
||||
public class LinearLayoutManager : LayoutManager
|
||||
{
|
||||
protected float lineHeight;
|
||||
|
||||
public LinearLayoutManager()
|
||||
{
|
||||
}
|
||||
public LinearLayoutManager() { }
|
||||
|
||||
public override Vector2 CalculateContentSize()
|
||||
{
|
||||
@ -22,7 +22,6 @@ namespace AlicizaX.UI
|
||||
position = index * (lineHeight + spacing.y) - spacing.y;
|
||||
return new Vector2(contentSize.x, position + padding.y * 2);
|
||||
}
|
||||
|
||||
position = index * (lineHeight + spacing.x) - spacing.x;
|
||||
return new Vector2(position + padding.x * 2, contentSize.y);
|
||||
}
|
||||
@ -35,7 +34,6 @@ namespace AlicizaX.UI
|
||||
position = index * (lineHeight + spacing.y) - ScrollPosition;
|
||||
return new Vector2(0, position + padding.y);
|
||||
}
|
||||
|
||||
position = index * (lineHeight + spacing.x) - ScrollPosition;
|
||||
return new Vector2(position + padding.x, 0);
|
||||
}
|
||||
@ -47,7 +45,6 @@ namespace AlicizaX.UI
|
||||
{
|
||||
return new Vector2(0, (len - lineHeight) / 2);
|
||||
}
|
||||
|
||||
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((viewportSize.x - lineHeight) / 2, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
[Serializable]
|
||||
public class MixedLayoutManager : LayoutManager
|
||||
{
|
||||
public MixedLayoutManager() { }
|
||||
|
||||
@ -4,10 +4,10 @@ using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
[Serializable]
|
||||
public class PageLayoutManager : LinearLayoutManager
|
||||
{
|
||||
[SerializeField]
|
||||
private float minScale;
|
||||
[SerializeField] private float minScale = 0.9f;
|
||||
|
||||
public PageLayoutManager()
|
||||
{
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a9bb27da68d4451a7d79cdb7abc1506
|
||||
timeCreated: 1748431180
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
|
||||
|
||||
internal interface IMixedObjectFactory<T> where T : class
|
||||
public interface IMixedObjectFactory<T> where T : class
|
||||
{
|
||||
T Create(string typeName);
|
||||
|
||||
@ -12,5 +10,4 @@ namespace SimpleObjectPool
|
||||
|
||||
bool Validate(string typeName, T obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
using System;
|
||||
|
||||
internal interface IMixedObjectPool<T> : IDisposable where T : class
|
||||
public interface IMixedObjectPool<T> : IDisposable where T : class
|
||||
{
|
||||
T Allocate(string typeName);
|
||||
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
|
||||
|
||||
internal interface IObjectFactory<T> where T : class
|
||||
public interface IObjectFactory<T> where T : class
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建对象
|
||||
@ -29,5 +27,4 @@ namespace SimpleObjectPool
|
||||
/// <returns></returns>
|
||||
bool Validate(T obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
using System;
|
||||
|
||||
internal interface IObjectPool : IDisposable
|
||||
public interface IObjectPool : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 从池子中分配一个可用对象,没有的话就创建一个
|
||||
@ -17,7 +17,7 @@ namespace SimpleObjectPool
|
||||
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();
|
||||
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
|
||||
|
||||
internal interface IPooledObject
|
||||
public interface IPooledObject
|
||||
{
|
||||
void Free();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
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;
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
using System;
|
||||
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 initialSize;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
internal class UnityComponentFactory<T> : IObjectFactory<T> where T : Component
|
||||
public class UnityComponentFactory<T> : IObjectFactory<T> where T : Component
|
||||
{
|
||||
private T template;
|
||||
private Transform parent;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
internal class UnityGameObjectFactory : IObjectFactory<GameObject>
|
||||
public class UnityGameObjectFactory : IObjectFactory<GameObject>
|
||||
{
|
||||
protected GameObject template;
|
||||
protected Transform parent;
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
internal class UnityMixedComponentFactory<T> : IMixedObjectFactory<T> where T : Component
|
||||
public class UnityMixedComponentFactory<T> : IMixedObjectFactory<T> where T : Component
|
||||
{
|
||||
protected T template;
|
||||
protected Transform parent;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
namespace SimpleObjectPool
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
internal class UnityMixedGameObjectFactory : IMixedObjectFactory<GameObject>
|
||||
public class UnityMixedGameObjectFactory : IMixedObjectFactory<GameObject>
|
||||
{
|
||||
protected GameObject template;
|
||||
protected Transform parent;
|
||||
@ -40,5 +40,4 @@ namespace SimpleObjectPool
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,13 +1,61 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -15,15 +63,119 @@ namespace AlicizaX.UI
|
||||
set => direction = value;
|
||||
}
|
||||
|
||||
[SerializeField] private Alignment alignment;
|
||||
|
||||
public Alignment Alignment
|
||||
{
|
||||
get => alignment;
|
||||
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
|
||||
{
|
||||
@ -38,328 +190,354 @@ namespace AlicizaX.UI
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField] private Vector2 spacing;
|
||||
|
||||
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 Scrollbar Scrollbar => scrollbar;
|
||||
|
||||
public Scroller Scroller => scroller;
|
||||
|
||||
public ViewProvider ViewProvider
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 OnScrollValueChanged;
|
||||
public Action OnMoveingChanged;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
if (_scroller != null)
|
||||
{
|
||||
_scroller.ScrollSpeed = scrollSpeed;
|
||||
_scroller.WheelSpeed = wheelSpeed;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void OnScrollChanged(float pos)
|
||||
{
|
||||
_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();
|
||||
}
|
||||
}
|
||||
}
|
||||
#region Unity Lifecycle
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
for (int i = 0; i < templates.Length; i++)
|
||||
{
|
||||
templates[i].gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
ConfigScroller();
|
||||
ConfigScrollbar();
|
||||
InitializeTemplates();
|
||||
ConfigureScroller();
|
||||
ConfigureScrollbar();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
#endregion
|
||||
|
||||
#region Initialization
|
||||
|
||||
private void InitializeTemplates()
|
||||
{
|
||||
viewProvider?.Dispose();
|
||||
if (templates == null) return;
|
||||
|
||||
for (int i = 0; i < templates.Length; i++)
|
||||
{
|
||||
if (templates[i] != null)
|
||||
{
|
||||
templates[i].gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureScroller()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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)
|
||||
{
|
||||
_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;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
#region Public Methods - Layout
|
||||
|
||||
public void Refresh()
|
||||
{
|
||||
ViewProvider.Clear();
|
||||
|
||||
startIndex = _layoutManager.GetStartIndex();
|
||||
endIndex = _layoutManager.GetEndIndex();
|
||||
for (int i = startIndex; i <= endIndex; i += _layoutManager.Unit)
|
||||
startIndex = layoutManager.GetStartIndex();
|
||||
endIndex = layoutManager.GetEndIndex();
|
||||
|
||||
for (int i = startIndex; i <= endIndex; i += layoutManager.Unit)
|
||||
{
|
||||
ViewProvider.CreateViewHolder(i);
|
||||
}
|
||||
|
||||
_layoutManager.DoItemAnimation();
|
||||
layoutManager.DoItemAnimation();
|
||||
}
|
||||
|
||||
public void RequestLayout()
|
||||
{
|
||||
_layoutManager.SetContentSize();
|
||||
layoutManager.SetContentSize();
|
||||
|
||||
if (_scroller == null) return;
|
||||
if (scroller == null) return;
|
||||
|
||||
_scroller.Direction = direction;
|
||||
_scroller.ViewSize = _layoutManager.ViewportSize;
|
||||
_scroller.ContentSize = _layoutManager.ContentSize;
|
||||
scroller.Direction = direction;
|
||||
scroller.ViewSize = layoutManager.ViewportSize;
|
||||
scroller.ContentSize = layoutManager.ContentSize;
|
||||
|
||||
if (Scrollbar != null && _scroller.ContentSize != Vector2.zero)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
UpdateScrollbarVisibility();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods - Scrolling
|
||||
|
||||
public float GetScrollPosition()
|
||||
{
|
||||
return _scroller ? _scroller.Position : 0;
|
||||
return scroller != null ? scroller.Position : 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Refresh();
|
||||
}
|
||||
|
||||
index %= _adapter.GetItemCount();
|
||||
index = index < 0 ? _adapter.GetItemCount() + index : index;
|
||||
UpdateCurrentIndex(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)
|
||||
{
|
||||
@ -368,11 +546,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SnapTo()
|
||||
{
|
||||
var index = _layoutManager.PositionToIndex(GetScrollPosition());
|
||||
ScrollTo(index, true);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: a01ce47da31a2e0438fd8d38b203c0d5, type: 3}
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
[Serializable]
|
||||
public class CircleScroller : Scroller
|
||||
{
|
||||
private Vector2 centerPosition;
|
||||
|
||||
@ -9,19 +9,7 @@ namespace AlicizaX.UI
|
||||
void ScrollTo(float position, bool smooth = false);
|
||||
}
|
||||
|
||||
public class ScrollerEvent : UnityEvent<float>
|
||||
{
|
||||
}
|
||||
|
||||
public class MoveStopEvent : UnityEvent
|
||||
{
|
||||
}
|
||||
|
||||
public class DraggingEvent : UnityEvent<bool>
|
||||
{
|
||||
}
|
||||
|
||||
public class MoveingEvent : UnityEvent
|
||||
{
|
||||
}
|
||||
public class ScrollerEvent : UnityEvent<float> { }
|
||||
public class MoveStopEvent : UnityEvent { }
|
||||
public class DraggingEvent : UnityEvent<bool> { }
|
||||
}
|
||||
|
||||
@ -1,26 +1,18 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
[Serializable]
|
||||
public class Scroller : MonoBehaviour, IScroller, IBeginDragHandler, IEndDragHandler, IDragHandler, IScrollHandler
|
||||
{
|
||||
protected float position;
|
||||
|
||||
public float Position
|
||||
{
|
||||
get => position;
|
||||
set => position = value;
|
||||
}
|
||||
public float Position { get => position; set => position = value; }
|
||||
|
||||
protected float velocity;
|
||||
public float Velocity => velocity;
|
||||
|
||||
protected Direction direction;
|
||||
|
||||
public Direction Direction
|
||||
{
|
||||
get => direction;
|
||||
@ -31,7 +23,6 @@ namespace AlicizaX.UI
|
||||
/// 内容所需要大小
|
||||
/// </summary>
|
||||
protected Vector2 contentSize;
|
||||
|
||||
public Vector2 ContentSize
|
||||
{
|
||||
get => contentSize;
|
||||
@ -42,7 +33,6 @@ namespace AlicizaX.UI
|
||||
/// 所在 View 的真实大小
|
||||
/// </summary>
|
||||
protected Vector2 viewSize;
|
||||
|
||||
public Vector2 ViewSize
|
||||
{
|
||||
get => viewSize;
|
||||
@ -50,7 +40,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected float scrollSpeed = 1f;
|
||||
|
||||
public float ScrollSpeed
|
||||
{
|
||||
get => scrollSpeed;
|
||||
@ -58,7 +47,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected float wheelSpeed = 30f;
|
||||
|
||||
public float WheelSpeed
|
||||
{
|
||||
get => wheelSpeed;
|
||||
@ -66,7 +54,6 @@ namespace AlicizaX.UI
|
||||
}
|
||||
|
||||
protected bool snap;
|
||||
|
||||
public bool Snap
|
||||
{
|
||||
get => snap;
|
||||
@ -76,38 +63,21 @@ namespace AlicizaX.UI
|
||||
protected ScrollerEvent scrollerEvent = new();
|
||||
protected MoveStopEvent moveStopEvent = 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 MoveingEvent OnMoveing
|
||||
{
|
||||
get => moveingEvent;
|
||||
set => moveingEvent = value;
|
||||
}
|
||||
public ScrollerEvent OnValueChanged { get => scrollerEvent; set => scrollerEvent = value; }
|
||||
|
||||
public ScrollerEvent OnValueChanged
|
||||
{
|
||||
get => scrollerEvent;
|
||||
set => scrollerEvent = value;
|
||||
}
|
||||
public MoveStopEvent OnMoveStoped { get => moveStopEvent; set => moveStopEvent = value; }
|
||||
|
||||
public MoveStopEvent OnMoveStoped
|
||||
{
|
||||
get => moveStopEvent;
|
||||
set => moveStopEvent = value;
|
||||
}
|
||||
|
||||
public DraggingEvent OnDragging
|
||||
{
|
||||
get => draggingEvent;
|
||||
set => draggingEvent = 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)
|
||||
{
|
||||
@ -151,10 +121,9 @@ namespace AlicizaX.UI
|
||||
position += velocity;
|
||||
|
||||
OnValueChanged?.Invoke(position);
|
||||
OnMoveing?.Invoke();
|
||||
}
|
||||
|
||||
public virtual void OnScrolled(PointerEventData eventData)
|
||||
public void OnScroll(PointerEventData eventData)
|
||||
{
|
||||
StopAllCoroutines();
|
||||
|
||||
@ -163,7 +132,7 @@ namespace AlicizaX.UI
|
||||
position += velocity;
|
||||
|
||||
OnValueChanged?.Invoke(position);
|
||||
OnMoveing?.Invoke();
|
||||
Inertia();
|
||||
Elastic();
|
||||
}
|
||||
|
||||
@ -184,7 +153,6 @@ namespace AlicizaX.UI
|
||||
{
|
||||
rate = Mathf.Max(0, 1 - (Mathf.Abs(position - MaxPosition) / ViewLength));
|
||||
}
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
@ -273,11 +241,5 @@ namespace AlicizaX.UI
|
||||
position = targetPos;
|
||||
OnValueChanged?.Invoke(position);
|
||||
}
|
||||
|
||||
|
||||
void IScrollHandler.OnScroll(PointerEventData eventData)
|
||||
{
|
||||
OnScrolled(eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
=> new UGList<TData>(recyclerView, onItemClick);
|
||||
3
Runtime/RecyclerView/UGList.cs.meta
Normal file
3
Runtime/RecyclerView/UGList.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd094e3cb2194cb193221ea9436a169a
|
||||
timeCreated: 1766729620
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 369d2829a7a2462ba93212b3d8afe0fa
|
||||
timeCreated: 1763615925
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19892a10438348b3b7e7cac3e2201b9e
|
||||
timeCreated: 1763615934
|
||||
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SimpleObjectPool;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using SimpleObjectPool;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
{
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AlicizaX.UI.Runtime;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI
|
||||
@ -8,7 +6,7 @@ namespace AlicizaX.UI
|
||||
/// <summary>
|
||||
/// 提供和管理 ViewHolder
|
||||
/// </summary>
|
||||
public abstract class ViewProvider : IDisposable
|
||||
public abstract class ViewProvider
|
||||
{
|
||||
private readonly List<ViewHolder> viewHolders = new();
|
||||
|
||||
@ -44,10 +42,10 @@ namespace AlicizaX.UI
|
||||
|
||||
string viewName = Adapter.GetViewName(i);
|
||||
var viewHolder = Allocate(viewName);
|
||||
viewHolder.OnStart();
|
||||
viewHolder.Name = viewName;
|
||||
viewHolder.Index = i;
|
||||
viewHolders.Add(viewHolder);
|
||||
|
||||
LayoutManager.Layout(viewHolder, i);
|
||||
Adapter.OnBindViewHolder(viewHolder, i);
|
||||
}
|
||||
@ -131,15 +129,5 @@ namespace AlicizaX.UI
|
||||
{
|
||||
return Adapter == null ? 0 : Adapter.GetItemCount();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var viewHolder in viewHolders)
|
||||
{
|
||||
Free(viewHolder.Name, viewHolder);
|
||||
}
|
||||
|
||||
viewHolders.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user