添加按比例缩放的表格计算逻辑,使用小于等于1的单元格尺寸来获取相对容器的尺寸
This commit is contained in:
@@ -75,5 +75,11 @@ namespace XericUI.XTable.Mapping
|
||||
int localCol = col % blockSizeX;
|
||||
return localRow * blockSizeX + localCol;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float ResolveSize(float rawSize, float axisBaseSize)
|
||||
{
|
||||
return rawSize > 0f && rawSize <= 1f ? rawSize * axisBaseSize : rawSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
=> TableData.IsMergeSource(row, col, out rowSpan, out colSpan);
|
||||
|
||||
/// <summary>
|
||||
/// 在末尾追加一行,默认行高来自 Config。
|
||||
/// 在末尾追加一行,默认行高来自 Config。尺寸在 (0, 1] 时按 viewport、父级或自身高度比例解析,> 1 时为像素。
|
||||
/// 行为:普通调用立即扩展行数组;CheckUpdate 内记录追加,结束时只重建一次。
|
||||
/// 建议:循环追加或随后填充新行时使用 CheckUpdate。
|
||||
/// </summary>
|
||||
@@ -367,7 +367,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在末尾追加一列,默认列宽来自 Config。
|
||||
/// 在末尾追加一列,默认列宽来自 Config。尺寸在 (0, 1] 时按 viewport、父级或自身宽度比例解析,> 1 时为像素。
|
||||
/// 行为:普通调用立即扩展列数组;CheckUpdate 内记录追加,结束时只重建一次。
|
||||
/// 建议:循环追加或随后填充新列时使用 CheckUpdate。
|
||||
/// </summary>
|
||||
@@ -395,7 +395,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置指定行的高度。
|
||||
/// 设置指定行的高度。尺寸在 (0, 1] 时按 viewport、父级或自身高度比例解析,> 1 时为像素。
|
||||
/// 行为:普通调用立即更新布局;CheckUpdate 内延后,最终按命令顺序应用。
|
||||
/// 建议:批量调整行高时使用 CheckUpdate。
|
||||
/// </summary>
|
||||
@@ -420,7 +420,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置指定列的宽度。
|
||||
/// 设置指定列的宽度。尺寸在 (0, 1] 时按 viewport、父级或自身宽度比例解析,> 1 时为像素。
|
||||
/// 行为:普通调用立即更新布局;CheckUpdate 内延后,最终按命令顺序应用。
|
||||
/// 建议:批量调整列宽时使用 CheckUpdate。
|
||||
/// </summary>
|
||||
@@ -672,6 +672,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
m_Assembler = new CellAssembler(ContentTransform, m_DefaultStyleNamespace);
|
||||
m_PrefabPool = new PrefabPrototypePool(ContentTransform);
|
||||
m_ActivePrefabMap = new Dictionary<(int, int), GameObject>();
|
||||
UpdateResolvedCellSizes();
|
||||
RecalculateTotalSize();
|
||||
CreateDefaultSampleData();
|
||||
CreateBackground();
|
||||
@@ -732,6 +733,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
m_Assembler = new CellAssembler(ContentTransform, m_DefaultStyleNamespace);
|
||||
m_PrefabPool = new PrefabPrototypePool(ContentTransform);
|
||||
m_ActivePrefabMap = new Dictionary<(int, int), GameObject>();
|
||||
UpdateResolvedCellSizes();
|
||||
RecalculateTotalSize();
|
||||
|
||||
// 恢复文本数据到新 TableData
|
||||
@@ -820,6 +822,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
m_PrefabPool = new PrefabPrototypePool(ContentTransform);
|
||||
m_ActivePrefabMap = new Dictionary<(int, int), GameObject>();
|
||||
MarkDirty(TableDirtyType.All);
|
||||
UpdateResolvedCellSizes();
|
||||
RecalculateTotalSize();
|
||||
CreateBackground();
|
||||
CreateViewportRenderer();
|
||||
@@ -881,6 +884,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
// 写回单元格文本与合并信息
|
||||
data.PopulateToTable(this);
|
||||
|
||||
UpdateResolvedCellSizes();
|
||||
RecalculateTotalSize();
|
||||
RequestRefresh(TableDirtyType.DataChanged | TableDirtyType.LayoutChanged, true);
|
||||
SetChildrenVisible(m_ChildrenVisible);
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace XericUI.XTable.Rendering.Component
|
||||
{
|
||||
// 计入 m_ContentOffset 以匹配单元格在 Content 中的实际渲染位置
|
||||
float cellLeft = GetColLeftX(col) + m_ContentOffset;
|
||||
float cellRight = cellLeft + m_ColWidths[col];
|
||||
float cellRight = cellLeft + m_ResolvedColWidths[col];
|
||||
float cellTop = GetRowTopY(row) + m_ContentOffset;
|
||||
float cellBottom = cellTop + m_RowHeights[row];
|
||||
float cellBottom = cellTop + m_ResolvedRowHeights[row];
|
||||
|
||||
return cellRight > m_VisibleRect.x && cellLeft < m_VisibleRect.xMax &&
|
||||
cellBottom > m_VisibleRect.y && cellTop < m_VisibleRect.yMax;
|
||||
@@ -43,16 +43,16 @@ namespace XericUI.XTable.Rendering.Component
|
||||
private float GetRowTopY(int row)
|
||||
{
|
||||
float y = 0;
|
||||
for (int i = 0; i < row && i < m_RowHeights.Length; i++)
|
||||
y += m_RowHeights[i];
|
||||
for (int i = 0; i < row && i < m_ResolvedRowHeights.Length; i++)
|
||||
y += m_ResolvedRowHeights[i];
|
||||
return y;
|
||||
}
|
||||
|
||||
private float GetColLeftX(int col)
|
||||
{
|
||||
float x = 0;
|
||||
for (int i = 0; i < col && i < m_ColWidths.Length; i++)
|
||||
x += m_ColWidths[i];
|
||||
for (int i = 0; i < col && i < m_ResolvedColWidths.Length; i++)
|
||||
x += m_ResolvedColWidths[i];
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -83,13 +83,13 @@ namespace XericUI.XTable.Rendering.Component
|
||||
private void RecalculateTotalSize()
|
||||
{
|
||||
m_TotalWidth = 0;
|
||||
if (m_ColWidths != null)
|
||||
foreach (float w in m_ColWidths)
|
||||
if (m_ResolvedColWidths != null)
|
||||
foreach (float w in m_ResolvedColWidths)
|
||||
m_TotalWidth += w;
|
||||
|
||||
m_TotalHeight = 0;
|
||||
if (m_RowHeights != null)
|
||||
foreach (float h in m_RowHeights)
|
||||
if (m_ResolvedRowHeights != null)
|
||||
foreach (float h in m_ResolvedRowHeights)
|
||||
m_TotalHeight += h;
|
||||
|
||||
m_ContentOffset = GetCellBorderWidth(m_DefaultStyleNamespace) * 0.5f;
|
||||
@@ -125,9 +125,9 @@ namespace XericUI.XTable.Rendering.Component
|
||||
ec = 0;
|
||||
|
||||
float accY = 0;
|
||||
for (int r = 0; r < m_RowHeights.Length; r++)
|
||||
for (int r = 0; r < m_ResolvedRowHeights.Length; r++)
|
||||
{
|
||||
float rowBottom = accY + m_RowHeights[r];
|
||||
float rowBottom = accY + m_ResolvedRowHeights[r];
|
||||
if (rowBottom > m_VisibleRect.y && accY < m_VisibleRect.yMax)
|
||||
{
|
||||
if (er == 0 && sr == 0) sr = r;
|
||||
@@ -139,9 +139,9 @@ namespace XericUI.XTable.Rendering.Component
|
||||
}
|
||||
|
||||
float accX = 0;
|
||||
for (int c = 0; c < m_ColWidths.Length; c++)
|
||||
for (int c = 0; c < m_ResolvedColWidths.Length; c++)
|
||||
{
|
||||
float colRight = accX + m_ColWidths[c];
|
||||
float colRight = accX + m_ResolvedColWidths[c];
|
||||
if (colRight > m_VisibleRect.x && accX < m_VisibleRect.xMax)
|
||||
{
|
||||
if (ec == 0 && sc == 0) sc = c;
|
||||
@@ -233,7 +233,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
cells.Add(new XTableQuadtreeCell { Row = r, Col = c, Namespace = ResolveCellNamespace(data) });
|
||||
}
|
||||
|
||||
m_Quadtree.Build(m_TotalWidth, m_TotalHeight, m_RowHeights, m_ColWidths, cells, Config.QuadtreeMaxCellsPerNode);
|
||||
m_Quadtree.Build(m_TotalWidth, m_TotalHeight, m_ResolvedRowHeights, m_ResolvedColWidths, cells, Config.QuadtreeMaxCellsPerNode);
|
||||
m_QuadtreeDirty = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -264,6 +264,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
}
|
||||
|
||||
// 标记脏并刷新
|
||||
UpdateResolvedCellSizes();
|
||||
RecalculateTotalSize();
|
||||
RequestRefresh(TableDirtyType.DataChanged | TableDirtyType.LayoutChanged, true);
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ namespace XericUI.XTable.Rendering.Component
|
||||
GetStyleColor = (ns, path, fallback) => GetStyleColor(ns, path, fallback),
|
||||
GetStyleInt = (ns, path, fallback) => GetStyleInt(ns, path, fallback),
|
||||
GetStyleFontAsset = (ns, path) => GetStyleFontAsset(ns, path),
|
||||
GetRowHeights = () => m_RowHeights,
|
||||
GetColWidths = () => m_ColWidths,
|
||||
GetRowHeights = () => m_ResolvedRowHeights,
|
||||
GetColWidths = () => m_ResolvedColWidths,
|
||||
GetTableData = () => m_TableData,
|
||||
GetDefaultStyleNamespace = () => m_DefaultStyleNamespace,
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XericLibrary.Runtime.MacroLibrary;
|
||||
using XericUI.XTable.Core;
|
||||
using XericUI.XTable.Rendering.Elements;
|
||||
#if UNITY_EDITOR
|
||||
@@ -134,16 +135,16 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
float cellX = GetCellContentX(col);
|
||||
float cellY = GetCellContentY(row);
|
||||
float cellW = m_ColWidths[col];
|
||||
float cellH = m_RowHeights[row];
|
||||
float cellW = m_ResolvedColWidths[col];
|
||||
float cellH = m_ResolvedRowHeights[row];
|
||||
|
||||
// 合并源:扩展尺寸
|
||||
if (TableData.IsMergeSource(row, col, out int mergeRS, out int mergeCS))
|
||||
{
|
||||
for (int i = 1; i < mergeCS && col + i < m_ColWidths.Length; i++)
|
||||
cellW += m_ColWidths[col + i];
|
||||
for (int i = 1; i < mergeRS && row + i < m_RowHeights.Length; i++)
|
||||
cellH += m_RowHeights[row + i];
|
||||
for (int i = 1; i < mergeCS && col + i < m_ResolvedColWidths.Length; i++)
|
||||
cellW += m_ResolvedColWidths[col + i];
|
||||
for (int i = 1; i < mergeRS && row + i < m_ResolvedRowHeights.Length; i++)
|
||||
cellH += m_ResolvedRowHeights[row + i];
|
||||
}
|
||||
|
||||
int cellId = row * m_ColWidths.Length + col;
|
||||
@@ -267,6 +268,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
if (m_RowHeights == null || m_ColWidths == null) return;
|
||||
if (m_RowHeights.Length == 0 || m_ColWidths.Length == 0) return;
|
||||
|
||||
UpdateResolvedCellSizes();
|
||||
CreateBackground();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
@@ -70,12 +70,12 @@ namespace XericUI.XTable.Rendering.Component
|
||||
internal bool TryGetCellFromTablePoint(Vector2 point, bool clamp, out int row, out int col)
|
||||
{
|
||||
row = col = -1;
|
||||
if (m_RowHeights == null || m_ColWidths == null || m_RowHeights.Length == 0 || m_ColWidths.Length == 0) return false;
|
||||
if (m_ResolvedRowHeights == null || m_ResolvedColWidths == null || m_ResolvedRowHeights.Length == 0 || m_ResolvedColWidths.Length == 0) return false;
|
||||
if (clamp) { point.x = Mathf.Clamp(point.x, 0, Mathf.Max(0, m_TotalWidth - .001f)); point.y = Mathf.Clamp(point.y, 0, Mathf.Max(0, m_TotalHeight - .001f)); }
|
||||
else if (point.x < 0 || point.y < 0 || point.x >= m_TotalWidth || point.y >= m_TotalHeight) return false;
|
||||
float cursor = 0; for (col = 0; col < m_ColWidths.Length && point.x >= (cursor += m_ColWidths[col]); col++) { }
|
||||
cursor = 0; for (row = 0; row < m_RowHeights.Length && point.y >= (cursor += m_RowHeights[row]); row++) { }
|
||||
if (row >= m_RowHeights.Length || col >= m_ColWidths.Length) return false;
|
||||
float cursor = 0; for (col = 0; col < m_ResolvedColWidths.Length && point.x >= (cursor += m_ResolvedColWidths[col]); col++) { }
|
||||
cursor = 0; for (row = 0; row < m_ResolvedRowHeights.Length && point.y >= (cursor += m_ResolvedRowHeights[row]); row++) { }
|
||||
if (row >= m_ResolvedRowHeights.Length || col >= m_ResolvedColWidths.Length) return false;
|
||||
if (m_TableData != null && m_TableData.TryGetMergeRect(row, col, out int sr, out int sc, out _, out _)) { row = sr; col = sc; }
|
||||
return true;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
float freezeWidth = GetColLeftX(Mathf.Clamp(m_FreezeColCount, 0, m_ColWidths.Length));
|
||||
float freezeHeight = GetRowTopY(Mathf.Clamp(m_FreezeRowCount, 0, m_RowHeights.Length));
|
||||
if (x < freezeWidth || y < freezeHeight) return;
|
||||
float width = rect.width - freezeWidth, height = rect.height - freezeHeight;
|
||||
float width = Mathf.Max(0f, rect.width - freezeWidth), height = Mathf.Max(0f, rect.height - freezeHeight);
|
||||
float threshold = Mathf.Min(m_SelectionAutoScrollEdgeThreshold, Mathf.Min(width, height) * .5f);
|
||||
float sx = GetAutoScrollSpeed(x - freezeWidth, width, threshold), sy = GetAutoScrollSpeed(y - freezeHeight, height, threshold);
|
||||
if (Mathf.Approximately(sx, 0) && Mathf.Approximately(sy, 0)) return;
|
||||
@@ -106,6 +106,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
private float GetAutoScrollSpeed(float point, float length, float threshold)
|
||||
{
|
||||
if (threshold <= 0f) return 0f;
|
||||
float direction = point < threshold ? -1f : point > length - threshold ? 1f : 0f;
|
||||
if (direction == 0f) return 0f;
|
||||
float distance = direction < 0f ? point : length - point;
|
||||
|
||||
@@ -108,6 +108,10 @@ namespace XericUI.XTable.Rendering.Component
|
||||
[System.NonSerialized] private UILineRendererV2 m_FrozenRowBorderRenderer;
|
||||
[System.NonSerialized] private UILineRendererV2 m_FrozenCornerBorderRenderer;
|
||||
|
||||
[NonSerialized] private float[] m_ResolvedRowHeights;
|
||||
[NonSerialized] private float[] m_ResolvedColWidths;
|
||||
[NonSerialized] private Vector2 m_LastLayoutBaseSize;
|
||||
|
||||
private float m_TotalWidth;
|
||||
private float m_TotalHeight;
|
||||
|
||||
@@ -147,6 +151,8 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
public float[] RowHeights => m_RowHeights;
|
||||
public float[] ColWidths => m_ColWidths;
|
||||
public float[] ResolvedRowHeights => m_ResolvedRowHeights;
|
||||
public float[] ResolvedColWidths => m_ResolvedColWidths;
|
||||
|
||||
/// <summary>冻结行数</summary>
|
||||
public int FreezeRowCount => m_FreezeRowCount;
|
||||
@@ -278,6 +284,7 @@ namespace XericUI.XTable.Rendering.Component
|
||||
m_Assembler = new CellAssembler(ContentTransform, m_DefaultStyleNamespace);
|
||||
m_PrefabPool = new PrefabPrototypePool(ContentTransform);
|
||||
m_ActivePrefabMap = new Dictionary<(int, int), GameObject>();
|
||||
UpdateResolvedCellSizes();
|
||||
RecalculateTotalSize();
|
||||
EnsureDefaultStyleNamespace();
|
||||
CreateDefaultSampleData();
|
||||
@@ -410,6 +417,51 @@ namespace XericUI.XTable.Rendering.Component
|
||||
|
||||
[System.NonSerialized] private bool m_IsRefreshingFromScroll;
|
||||
|
||||
private void OnRectTransformDimensionsChange()
|
||||
{
|
||||
Vector2 layoutBaseSize = GetLayoutBaseSize();
|
||||
if (layoutBaseSize != m_LastLayoutBaseSize)
|
||||
{
|
||||
m_LastLayoutBaseSize = layoutBaseSize;
|
||||
MarkDirty(TableDirtyType.LayoutChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private Vector2 GetLayoutBaseSize()
|
||||
{
|
||||
RectTransform baseTransform = m_ScrollRect != null && m_ScrollRect.viewport != null
|
||||
? m_ScrollRect.viewport
|
||||
: transform.parent as RectTransform;
|
||||
if (baseTransform == null) baseTransform = rectTransform;
|
||||
|
||||
Vector2 size = baseTransform != null ? baseTransform.rect.size : Vector2.zero;
|
||||
Vector2 selfSize = rectTransform != null ? rectTransform.rect.size : Vector2.zero;
|
||||
return new Vector2(size.x > 0f ? size.x : (m_LastLayoutBaseSize.x > 0f ? m_LastLayoutBaseSize.x : selfSize.x),
|
||||
size.y > 0f ? size.y : (m_LastLayoutBaseSize.y > 0f ? m_LastLayoutBaseSize.y : selfSize.y));
|
||||
}
|
||||
|
||||
private void UpdateResolvedCellSizes()
|
||||
{
|
||||
Vector2 baseSize = GetLayoutBaseSize();
|
||||
m_LastLayoutBaseSize = baseSize;
|
||||
if (m_RowHeights == null || m_ColWidths == null)
|
||||
{
|
||||
m_ResolvedRowHeights = null;
|
||||
m_ResolvedColWidths = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_ResolvedRowHeights == null || m_ResolvedRowHeights.Length != m_RowHeights.Length)
|
||||
m_ResolvedRowHeights = new float[m_RowHeights.Length];
|
||||
if (m_ResolvedColWidths == null || m_ResolvedColWidths.Length != m_ColWidths.Length)
|
||||
m_ResolvedColWidths = new float[m_ColWidths.Length];
|
||||
|
||||
for (int i = 0; i < m_RowHeights.Length; i++)
|
||||
m_ResolvedRowHeights[i] = XTableCoordinateUtility.ResolveSize(m_RowHeights[i], baseSize.y);
|
||||
for (int i = 0; i < m_ColWidths.Length; i++)
|
||||
m_ResolvedColWidths[i] = XTableCoordinateUtility.ResolveSize(m_ColWidths[i], baseSize.x);
|
||||
}
|
||||
|
||||
private void OnScrollValueChanged(Vector2 _)
|
||||
{
|
||||
if (IsCheckingUpdate) return;
|
||||
|
||||
Reference in New Issue
Block a user