改正了错别字。
修复了布局计算流程,现在可以手动定义固定行列数量了。
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
namespace XericUI.Core.Interface
|
||||
using XericUI.Helper;
|
||||
|
||||
namespace XericUI.Core.Interface
|
||||
{
|
||||
/// <summary>
|
||||
/// Xeric UI Vessel容器控制接口
|
||||
@@ -12,11 +14,12 @@
|
||||
/// <summary>
|
||||
/// 当前元素处于可见范围时(预载范围)
|
||||
/// </summary>
|
||||
public void UnderVisibal();
|
||||
public void UnderVisible();
|
||||
/// <summary>
|
||||
/// 当前元素离开可见范围时(预载范围)
|
||||
/// </summary>
|
||||
|
||||
public void OutOfVisibal();
|
||||
public void OutOfVisible();
|
||||
|
||||
public void UpdateLayout(GridLayoutCalculator.LayoutItem layoutData);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@
|
||||
{
|
||||
public class VesselBase
|
||||
{
|
||||
|
||||
public string VesselName;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace XericUI.Helper
|
||||
public static class GridLayoutCalculator
|
||||
{
|
||||
public static Vector2 Grid;
|
||||
|
||||
public struct LayoutItem
|
||||
{
|
||||
public Vector2 position; // anchoredPosition
|
||||
@@ -53,6 +54,7 @@ namespace XericUI.Helper
|
||||
cellSize = new Vector2(Mathf.Max(0.1f, cellSize.x), Mathf.Max(0.1f, cellSize.y));
|
||||
spacing = new Vector2(Mathf.Max(0f, spacing.x), Mathf.Max(0f, spacing.y));
|
||||
|
||||
// todo 这里的行列数限制了实际行列数,需要修改计算扩容
|
||||
// 1. 计算行列数
|
||||
int cellCountX, cellCountY;
|
||||
CalculateGridDimensions(childCount, containerSize, cellSize, spacing, padding,
|
||||
@@ -64,7 +66,7 @@ namespace XericUI.Helper
|
||||
startAxis, out actualCellCountX, out actualCellCountY);
|
||||
|
||||
Grid = new Vector2(actualCellCountX, actualCellCountY);
|
||||
|
||||
|
||||
// 3. 计算所需空间
|
||||
Vector2 requiredSpace = new Vector2(
|
||||
actualCellCountX * cellSize.x + Mathf.Max(0, actualCellCountX - 1) * spacing.x,
|
||||
@@ -76,18 +78,18 @@ namespace XericUI.Helper
|
||||
requiredSpace, containerSize, padding, childAlignment, startCorner);
|
||||
|
||||
// 5. 处理特殊情况
|
||||
|
||||
int childrenToMove = CalculateChildrenToMove(childCount, cellCountX, cellCountY,
|
||||
|
||||
int childrenToMove = CalculateChildrenToMove(childCount, cellCountX, cellCountY,
|
||||
constraint, constraintCount, startAxis);
|
||||
|
||||
// 6. 计算每个子项的位置
|
||||
int cornerX = (int)startCorner % 2; // 0=左, 1=右
|
||||
int cornerY = (int)startCorner / 2; // 0=上, 1=下
|
||||
int cornerX = (int)startCorner % 2; // 0=左, 1=右
|
||||
int cornerY = (int)startCorner / 2; // 0=上, 1=下
|
||||
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
int gridX, gridY;
|
||||
CalculateItemGridPosition(i, childCount, cellCountX, cellCountY, startAxis,
|
||||
CalculateItemGridPosition(i, childCount, cellCountX, cellCountY, startAxis,
|
||||
constraint, constraintCount, childrenToMove,
|
||||
actualCellCountX, actualCellCountY, out gridX, out gridY);
|
||||
|
||||
@@ -134,7 +136,7 @@ namespace XericUI.Helper
|
||||
}
|
||||
|
||||
private static float CalculateAxisStartOffset(
|
||||
int axis, // 0=X, 1=Y
|
||||
int axis, // 0=X, 1=Y
|
||||
float requiredSpace,
|
||||
float availableSpace,
|
||||
RectOffset padding,
|
||||
@@ -143,28 +145,28 @@ namespace XericUI.Helper
|
||||
{
|
||||
// 计算包含padding的总需求空间
|
||||
float requiredSpaceWithPadding = requiredSpace + (axis == 0 ? padding.horizontal : padding.vertical);
|
||||
|
||||
|
||||
// 计算剩余空间
|
||||
float surplusSpace = availableSpace - requiredSpaceWithPadding;
|
||||
|
||||
|
||||
// 获取对齐值(0=左/上, 0.5=中, 1=右/下)
|
||||
float alignmentValue = GetAlignmentOnAxis(axis, childAlignment);
|
||||
|
||||
|
||||
// 关键:根据startCorner调整基准点
|
||||
float baseOffset;
|
||||
if (axis == 0) // X轴
|
||||
if (axis == 0) // X轴
|
||||
{
|
||||
// 如果startCorner在右侧,基准点应该是availableSpace - padding.right - requiredSpace
|
||||
int cornerX = (int)startCorner % 2;
|
||||
baseOffset = (cornerX == 0) ? padding.left : (availableSpace - padding.right - requiredSpace);
|
||||
}
|
||||
else // Y轴
|
||||
else // Y轴
|
||||
{
|
||||
// 如果startCorner在底部,基准点应该是availableSpace - padding.bottom - requiredSpace
|
||||
int cornerY = (int)startCorner / 2;
|
||||
baseOffset = (cornerY == 0) ? padding.top : (availableSpace - padding.bottom - requiredSpace);
|
||||
}
|
||||
|
||||
|
||||
// 应用对齐(在剩余空间内)
|
||||
return baseOffset + surplusSpace * alignmentValue;
|
||||
}
|
||||
@@ -186,7 +188,7 @@ namespace XericUI.Helper
|
||||
// 计算基础位置(不考虑corner翻转)
|
||||
if (startAxis == GridLayoutGroup.Axis.Horizontal)
|
||||
{
|
||||
if (constraint == GridLayoutGroup.Constraint.FixedRowCount &&
|
||||
if (constraint == GridLayoutGroup.Constraint.FixedRowCount &&
|
||||
childrenToMove > 0 && childCount - index <= childrenToMove)
|
||||
{
|
||||
// 计算偏移量,确保gridY不会为负数
|
||||
@@ -202,7 +204,7 @@ namespace XericUI.Helper
|
||||
}
|
||||
else
|
||||
{
|
||||
if (constraint == GridLayoutGroup.Constraint.FixedColumnCount &&
|
||||
if (constraint == GridLayoutGroup.Constraint.FixedColumnCount &&
|
||||
childrenToMove > 0 && childCount - index <= childrenToMove)
|
||||
{
|
||||
// 计算偏移量,确保gridX不会为负数
|
||||
@@ -230,7 +232,7 @@ namespace XericUI.Helper
|
||||
return 0;
|
||||
|
||||
int cellsPerMainAxis = startAxis == GridLayoutGroup.Axis.Horizontal ? cellCountX : cellCountY;
|
||||
|
||||
|
||||
if (cellsPerMainAxis <= 0)
|
||||
return 0;
|
||||
|
||||
@@ -240,7 +242,7 @@ namespace XericUI.Helper
|
||||
|
||||
int childrenToMove = constraintCount - (int)rowsNeeded;
|
||||
childrenToMove += Mathf.FloorToInt((float)childrenToMove / Mathf.Max(1f, (float)cellsPerMainAxis - 1));
|
||||
|
||||
|
||||
if (childCount % cellsPerMainAxis == 1)
|
||||
childrenToMove += 1;
|
||||
|
||||
@@ -262,34 +264,34 @@ namespace XericUI.Helper
|
||||
cellCountX = 1;
|
||||
cellCountY = 1;
|
||||
|
||||
if (constraint == GridLayoutGroup.Constraint.FixedColumnCount)
|
||||
switch (constraint)
|
||||
{
|
||||
cellCountX = constraintCount;
|
||||
if (childCount > cellCountX)
|
||||
cellCountY = childCount / cellCountX + (childCount % cellCountX > 0 ? 1 : 0);
|
||||
}
|
||||
else if (constraint == GridLayoutGroup.Constraint.FixedRowCount)
|
||||
{
|
||||
cellCountY = constraintCount;
|
||||
if (childCount > cellCountY)
|
||||
cellCountX = childCount / cellCountY + (childCount % cellCountY > 0 ? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
float availableWidth = containerSize.x - padding.horizontal;
|
||||
float availableHeight = containerSize.y - padding.vertical;
|
||||
case GridLayoutGroup.Constraint.FixedColumnCount:
|
||||
cellCountX = constraintCount;
|
||||
if (childCount > cellCountX)
|
||||
cellCountY = childCount / cellCountX + (childCount % cellCountX > 0 ? 1 : 0);
|
||||
break;
|
||||
case GridLayoutGroup.Constraint.FixedRowCount:
|
||||
cellCountY = constraintCount;
|
||||
if (childCount > cellCountY)
|
||||
cellCountX = childCount / cellCountY + (childCount % cellCountY > 0 ? 1 : 0);
|
||||
break;
|
||||
default:
|
||||
float availableWidth = containerSize.x - padding.horizontal;
|
||||
float availableHeight = containerSize.y - padding.vertical;
|
||||
|
||||
if (cellSize.x + spacing.x > 0)
|
||||
cellCountX = Mathf.Max(1,
|
||||
Mathf.FloorToInt((availableWidth + spacing.x + 0.001f) / (cellSize.x + spacing.x)));
|
||||
else
|
||||
cellCountX = int.MaxValue;
|
||||
if (cellSize.x + spacing.x > 0)
|
||||
cellCountX = Mathf.Max(1,
|
||||
Mathf.FloorToInt((availableWidth + spacing.x + 0.001f) / (cellSize.x + spacing.x)));
|
||||
else
|
||||
cellCountX = int.MaxValue;
|
||||
|
||||
if (cellSize.y + spacing.y > 0)
|
||||
cellCountY = Mathf.Max(1,
|
||||
Mathf.FloorToInt((availableHeight + spacing.y + 0.001f) / (cellSize.y + spacing.y)));
|
||||
else
|
||||
cellCountY = int.MaxValue;
|
||||
if (cellSize.y + spacing.y > 0)
|
||||
cellCountY = Mathf.Max(1,
|
||||
Mathf.FloorToInt((availableHeight + spacing.y + 0.001f) / (cellSize.y + spacing.y)));
|
||||
else
|
||||
cellCountY = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,15 +323,14 @@ namespace XericUI.Helper
|
||||
else
|
||||
actualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(childCount / (float)cellCountY));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static float GetAlignmentOnAxis(int axis, TextAnchor childAlignment)
|
||||
{
|
||||
if (axis == 0)
|
||||
return ((int)childAlignment % 3) * (1f / 3f); // 0, 0.333, 0.666
|
||||
return ((int)childAlignment % 3) * (1f / 3f); // 0, 0.333, 0.666
|
||||
else
|
||||
return ((int)childAlignment / 3) * 0.5f; // 0, 0.5, 1
|
||||
return ((int)childAlignment / 3) * 0.5f; // 0, 0.5, 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,15 @@ namespace XericUI.Helper
|
||||
{
|
||||
public static class UIVesselHelper
|
||||
{
|
||||
public static void CallVisibal(this IUIVesselVisibalControl control, bool underVisible)
|
||||
public static void CallVisible(this IUIVesselVisibalControl control, bool underVisible)
|
||||
{
|
||||
if (underVisible)
|
||||
{
|
||||
control.UnderVisibal();
|
||||
control.UnderVisible();
|
||||
}
|
||||
else
|
||||
{
|
||||
control.OutOfVisibal();
|
||||
control.OutOfVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
using XericLibrary.Runtime.Debuger;
|
||||
using XericLibrary.Runtime.MacroLibrary;
|
||||
using XericUI.Core.Interface;
|
||||
using XericUI.Helper;
|
||||
@@ -27,8 +29,7 @@ namespace XericUI.OverrideLayout
|
||||
{
|
||||
#region 字段属性
|
||||
|
||||
[Tooltip("启用自动剔除功能")] [SerializeField]
|
||||
protected bool m_enableAdvancedFunc = true;
|
||||
[Tooltip("启用自动剔除功能")] [SerializeField] protected bool m_enableAdvancedFunc = true;
|
||||
|
||||
[Tooltip("容器预加载像素范围")] [SerializeField]
|
||||
protected float m_preloadMargin = 200f;
|
||||
@@ -46,7 +47,11 @@ namespace XericUI.OverrideLayout
|
||||
[SerializeField] protected GridLayoutGroup.Corner m_startCorner = GridLayoutGroup.Corner.UpperLeft;
|
||||
[SerializeField] protected GridLayoutGroup.Axis m_startAxis = GridLayoutGroup.Axis.Horizontal;
|
||||
[SerializeField] protected TextAnchor m_childAlignment = TextAnchor.UpperLeft;
|
||||
[SerializeField] protected GridLayoutGroup.Constraint m_constraint = GridLayoutGroup.Constraint.Flexible;
|
||||
|
||||
[SerializeField]
|
||||
protected GridLayoutGroup.Constraint m_constraint = GridLayoutGroup.Constraint.FixedColumnCount;
|
||||
|
||||
[SerializeField] protected int m_constraintCount = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 对象池
|
||||
@@ -67,7 +72,7 @@ namespace XericUI.OverrideLayout
|
||||
UpdateContentLayout(1, value.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 布局参考
|
||||
@@ -80,13 +85,16 @@ namespace XericUI.OverrideLayout
|
||||
private Vector2 _lastContextAnchoredPosition;
|
||||
|
||||
private List<GridLayoutCalculator.LayoutItem> _layoutItems;
|
||||
|
||||
|
||||
private Queue<RectTransform> _activeQueue = new Queue<RectTransform>();
|
||||
|
||||
private bool layoutHasRebuildAtThisFrame;
|
||||
private bool layoutDirty;
|
||||
private bool indexMapDirty;
|
||||
|
||||
|
||||
private Vector2 visibleMin;
|
||||
private Vector2 visibleMax;
|
||||
|
||||
#endregion
|
||||
|
||||
[Serializable]
|
||||
@@ -95,30 +103,55 @@ namespace XericUI.OverrideLayout
|
||||
public GridLayoutCalculator.LayoutItem layout;
|
||||
public int index { get; internal set; }
|
||||
protected internal XericScrollRect parentScrollRect;
|
||||
private bool _uiVisibal;
|
||||
protected bool _uiVisibal;
|
||||
|
||||
protected GameObject item;
|
||||
public RectTransform itemRectTransform => item ? item.RectTransform() : null;
|
||||
public IUIVesselVisibalControl ItemUIVesselVisibalControlComponent => item ? itemRectTransform.GetComponent<IUIVesselVisibalControl>() : null;
|
||||
|
||||
/// <summary>
|
||||
/// 滚动框如何定位到接口(此接口返回的对象将用于生命周期管理,否则退化成简单的组件显影)
|
||||
/// </summary>
|
||||
public virtual IUIVesselVisibalControl ItemUIVesselVisibalControlComponent => this;
|
||||
|
||||
public bool GetUIVisibal => _uiVisibal;
|
||||
|
||||
public virtual void UnderVisibal()
|
||||
public virtual void UnderVisible()
|
||||
{
|
||||
SetIsVisible(true);
|
||||
item = parentScrollRect.childrenPool.Get();
|
||||
parentScrollRect.UpdateChildPivot(layout, item.RectTransform());
|
||||
itemRectTransform.anchoredPosition = layout.position;
|
||||
RefreshPivot();
|
||||
}
|
||||
|
||||
public virtual void OutOfVisibal()
|
||||
{
|
||||
public virtual void OutOfVisible()
|
||||
{
|
||||
SetIsVisible(false);
|
||||
parentScrollRect.childrenPool.DirectlyRelease(item);
|
||||
item = null;
|
||||
}
|
||||
|
||||
protected void SetIsVisible(bool visible)
|
||||
{
|
||||
_uiVisibal = visible;
|
||||
}
|
||||
|
||||
protected void RefreshPivot()
|
||||
{
|
||||
if (!item)
|
||||
{
|
||||
Debug.LogError($"滚动视图的实体对象在刷新前并未指定,请先指定{nameof(item)}后再调用{nameof(RefreshPivot)}");
|
||||
}
|
||||
|
||||
parentScrollRect.UpdateChildPivot(layout, item.RectTransform());
|
||||
itemRectTransform.anchoredPosition = layout.position;
|
||||
}
|
||||
|
||||
public void UpdateLayout(GridLayoutCalculator.LayoutItem layoutData)
|
||||
{
|
||||
layout = layoutData;
|
||||
}
|
||||
|
||||
public Vector2 WorldAnchoredPosition(RectTransform parentContent)
|
||||
=> parentContent.TransformPoint(itemRectTransform.anchoredPosition);
|
||||
}
|
||||
|
||||
#region 生命周期
|
||||
@@ -127,6 +160,7 @@ namespace XericUI.OverrideLayout
|
||||
private Vector3[] vertex1 = new Vector3[4];
|
||||
private Vector3[] vertex2 = new Vector3[4];
|
||||
private Vector3[] vertex3 = new Vector3[4];
|
||||
|
||||
private void OnDrawGizmosSelected()
|
||||
{
|
||||
var lossyScale = transform.lossyScale;
|
||||
@@ -157,6 +191,29 @@ namespace XericUI.OverrideLayout
|
||||
MacroGizmosDraw.DrawGizmos2RectLinkCube(vertex3, vertex1, Color.cyan, Color.red, true);
|
||||
MacroGizmosDraw.Label(vertex3[1], "preload Rect");
|
||||
MacroGizmosDraw.Label(vertex1[1], "display Rect");
|
||||
|
||||
if (!Application.isPlaying) return;
|
||||
|
||||
Gizmos.color = Color.magenta;
|
||||
MacroGizmosDraw.DrawGizmosRectLine(visibleMin - Vector2.one, visibleMax - Vector2.one);
|
||||
|
||||
var corners = new Vector3[4];
|
||||
foreach (var data in _childrenDatas)
|
||||
{
|
||||
if (data.GetUIVisibal)
|
||||
{
|
||||
Gizmos.color = Color.green;
|
||||
data.itemRectTransform.GetWorldCorners(corners);
|
||||
MacroGizmosDraw.DrawPolygonLineByPointArray(corners);
|
||||
MacroGizmosDraw.Label(corners[0], $"[{data.index}] 使用中");
|
||||
}
|
||||
else
|
||||
{
|
||||
Gizmos.color = Color.red;
|
||||
MacroGizmosDraw.DrawGizmosRectAtPoint(data.layout.position, data.layout.size);
|
||||
MacroGizmosDraw.Label(data.layout.position, $"[{data.index}] 已回收");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnValidate()
|
||||
@@ -221,16 +278,6 @@ namespace XericUI.OverrideLayout
|
||||
protected override void LateUpdate()
|
||||
{
|
||||
layoutHasRebuildAtThisFrame = false;
|
||||
base.LateUpdate();
|
||||
// 布局刷新
|
||||
if (layoutDirty)
|
||||
{
|
||||
layoutDirty = false;
|
||||
// 常规的刷新依赖视图的更新,如果这一帧只增删了对象,但是视图没有移动,那么这里就会执行更新
|
||||
if (layoutHasRebuildAtThisFrame)
|
||||
UpdateAAMVSVisibleStatus();
|
||||
RefreshLayout();
|
||||
}
|
||||
// 全部索引刷新
|
||||
if (indexMapDirty)
|
||||
{
|
||||
@@ -238,6 +285,19 @@ namespace XericUI.OverrideLayout
|
||||
for (int i = 0; i < _childrenDatas.Count; i++)
|
||||
_childrenDatas[i].index = i;
|
||||
}
|
||||
|
||||
// 重新计算布局
|
||||
if (layoutDirty)
|
||||
RefreshLayout();
|
||||
base.LateUpdate();
|
||||
// 布局刷新
|
||||
if (layoutDirty)
|
||||
{
|
||||
layoutDirty = false;
|
||||
// 常规的刷新依赖视图的更新,如果这一帧只增删了对象,但是视图没有移动,那么这里就会执行更新
|
||||
if (!layoutHasRebuildAtThisFrame)
|
||||
UpdateAAMVSVisibleStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3[] viewportVertex = new Vector3[4];
|
||||
@@ -252,16 +312,17 @@ namespace XericUI.OverrideLayout
|
||||
// 手动计算视口在content空间的矩形
|
||||
viewport.GetWorldCorners(viewportVertex);
|
||||
var viewportRect = new Rect(
|
||||
content.InverseTransformPoint(viewportVertex[0]),
|
||||
content.InverseTransformPoint(viewportVertex[2]) - content.InverseTransformPoint(viewportVertex[0]));
|
||||
viewportVertex[0],
|
||||
viewportVertex[2] - viewportVertex[0]);
|
||||
|
||||
var contentRect = content.rect;
|
||||
// 计算预加载边距(考虑content缩放)
|
||||
// var scaledMargin = preloadMargin / ((content.lossyScale.x + content.lossyScale.y) * 0.5f);
|
||||
|
||||
// 扩展可见区域边界
|
||||
var visibleMin = viewportRect.min - new Vector2(m_preloadMargin, m_preloadMargin);
|
||||
var visibleMax = viewportRect.max + new Vector2(m_preloadMargin, -m_preloadMargin);
|
||||
var preloadMarginVec2 = new Vector2(m_preloadMargin, m_preloadMargin);
|
||||
visibleMin = viewportRect.min - preloadMarginVec2;
|
||||
visibleMax = viewportRect.max + preloadMarginVec2;
|
||||
|
||||
// 获取当前滚动归一化位置
|
||||
// var scrollPos = new Vector2(
|
||||
@@ -275,9 +336,9 @@ namespace XericUI.OverrideLayout
|
||||
{
|
||||
var visControl = childData.ItemUIVesselVisibalControlComponent;
|
||||
var isVisControlValid = visControl != null;
|
||||
|
||||
|
||||
// 直接使用anchoredPosition进行边界检测
|
||||
var childPos = childRectTransform.anchoredPosition;
|
||||
var childPos = childData.WorldAnchoredPosition(content);
|
||||
var isVisible = CheckIsVisibal(childPos);
|
||||
var nowActive = childRectTransform.GetActivity();
|
||||
|
||||
@@ -291,23 +352,20 @@ namespace XericUI.OverrideLayout
|
||||
|
||||
// 向成员发送状态(如果成员没有实现接口,就直接通过可见性控制)
|
||||
if (isVisControlValid)
|
||||
visControl.CallVisibal(isVisible);
|
||||
visControl.CallVisible(isVisible);
|
||||
else
|
||||
childRectTransform.gameObject.SetActive(isVisible);
|
||||
}
|
||||
else
|
||||
{
|
||||
var isVisible = CheckIsVisibal(childData.layout.position);
|
||||
if (isVisible)
|
||||
{
|
||||
childData.UnderVisibal();
|
||||
}
|
||||
}
|
||||
if (!CheckIsVisibal(childData.layout.position))
|
||||
childData.UnderVisible();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CheckIsVisibal(Vector2 pos)
|
||||
{
|
||||
return
|
||||
return
|
||||
pos.x >= visibleMin.x &&
|
||||
pos.x <= visibleMax.x &&
|
||||
pos.y >= visibleMin.y &&
|
||||
@@ -315,8 +373,6 @@ namespace XericUI.OverrideLayout
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 数据管理
|
||||
@@ -324,13 +380,34 @@ namespace XericUI.OverrideLayout
|
||||
/// <summary>
|
||||
/// 添加一个子项(自行重写这个子项类型数据结构,基于其中的生命周期函数完成内容的更新)
|
||||
/// </summary>
|
||||
/// <param name="Data"></param>
|
||||
public void AddChildData(ScrollItemData Data)
|
||||
/// <param name="data"></param>
|
||||
public void AddChildData(ScrollItemData data)
|
||||
{
|
||||
layoutDirty = true;
|
||||
Data.index = _childrenDatas.Count;
|
||||
Data.parentScrollRect = this;
|
||||
_childrenDatas.Add(Data);
|
||||
data.index = _childrenDatas.Count;
|
||||
data.parentScrollRect = this;
|
||||
_childrenDatas.Add(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个子项在倒序的多少项之前
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="invertedOrder">指定这个项目插入在倒序的第几位</param>
|
||||
/// <remarks>
|
||||
/// 比如一个视图中有不同的几种对象,如常规对象和新建对象按钮,将这个对象插入在新建对象之前
|
||||
/// </remarks>
|
||||
public void AddChildData(ScrollItemData data, int invertedOrder)
|
||||
{
|
||||
layoutDirty = true;
|
||||
indexMapDirty = true;
|
||||
data.parentScrollRect = this;
|
||||
|
||||
var insertIndex = _childrenDatas.Count - invertedOrder;
|
||||
insertIndex = Mathf.Clamp(insertIndex, 0, _childrenDatas.Count);
|
||||
_childrenDatas.Insert(insertIndex, data);
|
||||
// for (int i = 0; i < _childrenDatas.Count; i++)
|
||||
// _childrenDatas[i].index = i;
|
||||
}
|
||||
|
||||
public void RemoveChildData(int index)
|
||||
@@ -339,7 +416,7 @@ namespace XericUI.OverrideLayout
|
||||
indexMapDirty = true;
|
||||
// 如果可见,先移除可见性
|
||||
if (_childrenDatas[index].GetUIVisibal)
|
||||
_childrenDatas[index].OutOfVisibal();
|
||||
_childrenDatas[index].OutOfVisible();
|
||||
_childrenDatas.RemoveAt(index);
|
||||
}
|
||||
|
||||
@@ -349,7 +426,7 @@ namespace XericUI.OverrideLayout
|
||||
indexMapDirty = true;
|
||||
// 如果可见,先移除可见性
|
||||
if (index.GetUIVisibal)
|
||||
index.OutOfVisibal();
|
||||
index.OutOfVisible();
|
||||
_childrenDatas.Remove(index);
|
||||
}
|
||||
|
||||
@@ -360,10 +437,10 @@ namespace XericUI.OverrideLayout
|
||||
// 如果可见,先移除可见性
|
||||
foreach (var data in _childrenDatas)
|
||||
if (data.GetUIVisibal)
|
||||
data.OutOfVisibal();
|
||||
data.OutOfVisible();
|
||||
_childrenDatas.Clear();
|
||||
}
|
||||
|
||||
|
||||
public ScrollItemData GetChildData(int index)
|
||||
{
|
||||
return _childrenDatas[index];
|
||||
@@ -375,18 +452,28 @@ namespace XericUI.OverrideLayout
|
||||
|
||||
private void RefreshLayout()
|
||||
{
|
||||
var layouts = GetChildrenLayout(content.transform.childCount);
|
||||
Debug.Log("刷新");
|
||||
var layouts = GetChildrenLayout(_childrenDatas.Count);
|
||||
for (int i = 0; i < layouts.Count; i++)
|
||||
{
|
||||
var trans = content.transform.GetChild(i) as RectTransform;
|
||||
UpdateChildPivot(layouts[i], trans);
|
||||
trans.anchoredPosition = layouts[i].position;
|
||||
trans.SetDeltaSize(m_cellSize);
|
||||
var childData = _childrenDatas[i];
|
||||
childData.UpdateLayout(layouts[i]);
|
||||
|
||||
var trans = childData.itemRectTransform;
|
||||
if (trans)
|
||||
{
|
||||
UpdateChildPivot(layouts[i], trans); // 先更新枢轴
|
||||
if (trans != null)
|
||||
{
|
||||
trans.anchoredPosition = layouts[i].position;
|
||||
trans.SetDeltaSize(m_cellSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RefreshContentSizeByChildrenLayouts(layouts);
|
||||
}
|
||||
|
||||
|
||||
private void UpdateContentLayout(int axis, float overrideSize)
|
||||
{
|
||||
content.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, overrideSize);
|
||||
@@ -398,24 +485,25 @@ namespace XericUI.OverrideLayout
|
||||
private void RefreshContentSizeByChildrenLayouts(List<GridLayoutCalculator.LayoutItem> layoutItems)
|
||||
{
|
||||
if (layoutItems.Count == 0) return;
|
||||
|
||||
|
||||
var first = layoutItems[0];
|
||||
var last = layoutItems[^1];
|
||||
|
||||
var size = first.position - last.position;
|
||||
size = size.Abs();
|
||||
|
||||
|
||||
// 计算实际使用的行列数
|
||||
int maxRow = 0;
|
||||
int maxColumn = 0;
|
||||
int maxRow = (int)GridLayoutCalculator.Grid.x;
|
||||
int maxColumn = (int)GridLayoutCalculator.Grid.y;
|
||||
foreach (var item in layoutItems)
|
||||
{
|
||||
maxRow = Mathf.Max(maxRow, item.rowIndex);
|
||||
maxColumn = Mathf.Max(maxColumn, item.columnIndex);
|
||||
}
|
||||
|
||||
int actualCellCountX = maxColumn + 1;
|
||||
int actualCellCountY = maxRow + 1;
|
||||
|
||||
|
||||
var spacing = new Vector2((actualCellCountX - 1) * m_spacing.x, (actualCellCountY - 1) * m_spacing.y);
|
||||
switch (m_startAxis)
|
||||
{
|
||||
@@ -425,9 +513,10 @@ namespace XericUI.OverrideLayout
|
||||
break;
|
||||
case GridLayoutGroup.Axis.Vertical:
|
||||
size.x = Mathf.Max(size.x + m_spacing.x, m_cellSize.x);
|
||||
size.y = Mathf.Max(size.y, viewport.rect.height);
|
||||
size.y = Mathf.Max(size.y, viewport.rect.height);
|
||||
break;
|
||||
}
|
||||
|
||||
ContextSize = size;
|
||||
}
|
||||
|
||||
@@ -437,7 +526,7 @@ namespace XericUI.OverrideLayout
|
||||
{
|
||||
// todo 对齐算法总的方向应该是写错了,找找
|
||||
GridLayoutGroup.Corner.UpperLeft => new Vector2(0, 1),
|
||||
GridLayoutGroup.Corner.UpperRight => new Vector2(1, 1),
|
||||
GridLayoutGroup.Corner.UpperRight => new Vector2(1, 1),
|
||||
GridLayoutGroup.Corner.LowerLeft => new Vector2(0, 0),
|
||||
GridLayoutGroup.Corner.LowerRight => new Vector2(1, 0),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
@@ -461,21 +550,23 @@ namespace XericUI.OverrideLayout
|
||||
{
|
||||
var first = layoutItems[0];
|
||||
var last = layoutItems[^1];
|
||||
|
||||
|
||||
// first.position
|
||||
}
|
||||
|
||||
|
||||
private List<GridLayoutCalculator.LayoutItem> GetChildrenLayout(int childrenCount)
|
||||
{
|
||||
// 根据约束类型设置合适的 constraintCount
|
||||
int constraintCount = 0;
|
||||
if (m_constraint == GridLayoutGroup.Constraint.FixedColumnCount || m_constraint == GridLayoutGroup.Constraint.FixedRowCount)
|
||||
int constraintCount = m_constraint switch
|
||||
{
|
||||
// 这里可以根据实际需求设置合适的约束数量
|
||||
// 暂时使用一个默认值,实际项目中可能需要从外部传入或通过其他方式计算
|
||||
constraintCount = 3;
|
||||
}
|
||||
|
||||
GridLayoutGroup.Constraint.FixedColumnCount => Mathf.CeilToInt(m_cellSize.x / ContextSize.x),
|
||||
GridLayoutGroup.Constraint.FixedRowCount => Mathf.CeilToInt(m_cellSize.y / ContextSize.y),
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
if (m_constraintCount > 0)
|
||||
constraintCount = m_constraintCount;
|
||||
|
||||
return GridLayoutCalculator.CalculateGridLayout(
|
||||
_layoutItems,
|
||||
childCount: childrenCount,
|
||||
|
||||
Reference in New Issue
Block a user