添加合并单元格的用法。

This commit is contained in:
2026-06-28 23:36:07 +08:00
parent f20033743d
commit b7963afe30
3 changed files with 282 additions and 41 deletions
+141 -12
View File
@@ -3,6 +3,7 @@ using UnityEditor;
using UnityEngine; using UnityEngine;
using XericLibrary.Runtime.SuperStyleSheet; using XericLibrary.Runtime.SuperStyleSheet;
using XericUI.XTable.Core;
using XericUI.XTable.Mapping; using XericUI.XTable.Mapping;
using XericUI.XTable.Rendering.Component; using XericUI.XTable.Rendering.Component;
@@ -445,18 +446,42 @@ namespace XericUIEditor.XTable
{ {
Color lineColor = new Color(0.5f, 0.5f, 0.55f, 0.18f); Color lineColor = new Color(0.5f, 0.5f, 0.55f, 0.18f);
// 水平网格线(跳过合并区域内的线)
float y = tr.y; float y = tr.y;
for (int r = 0; r < rh.Length; r++) for (int r = 0; r < rh.Length; r++)
{ {
y += rh[r] * yScale; y += rh[r] * yScale;
EditorGUI.DrawRect(new Rect(tr.x, y, tr.width, 1), lineColor);
// 检查此行是否在合并区域内(非底部边界的行)
bool skipLine = false;
if (s_ActiveTable != null && r + 1 < rh.Length)
{
var data = s_ActiveTable.TableData;
if (data != null && data.IsCellMerged(r + 1, 0))
skipLine = true;
}
if (!skipLine)
EditorGUI.DrawRect(new Rect(tr.x, y, tr.width, 1), lineColor);
} }
// 垂直网格线(跳过合并区域内的线)
float x = tr.x; float x = tr.x;
for (int c = 0; c < cw.Length; c++) for (int c = 0; c < cw.Length; c++)
{ {
x += cw[c] * xScale; x += cw[c] * xScale;
EditorGUI.DrawRect(new Rect(x, tr.y, 1, tr.height), lineColor);
// 检查此列是否在合并区域内(非右侧边界的列)
bool skipLine = false;
if (s_ActiveTable != null && c + 1 < cw.Length)
{
var data = s_ActiveTable.TableData;
if (data != null && data.IsCellMerged(0, c + 1))
skipLine = true;
}
if (!skipLine)
EditorGUI.DrawRect(new Rect(x, tr.y, 1, tr.height), lineColor);
} }
} }
@@ -471,6 +496,10 @@ namespace XericUIEditor.XTable
int sc = table.SelectedCol; int sc = table.SelectedCol;
if (sr < 0 || sc < 0 || sr >= rh.Length || sc >= cw.Length) return; if (sr < 0 || sc < 0 || sr >= rh.Length || sc >= cw.Length) return;
// 获取选中单元格的实际显示范围(合并源需要扩展)
int hlRowSpan = 1, hlColSpan = 1;
table.IsMergeSource(sr, sc, out hlRowSpan, out hlColSpan);
if (table.HasMultiSelection) if (table.HasMultiSelection)
{ {
int minR = Mathf.Min(table.SelectStartRow, table.SelectEndRow); int minR = Mathf.Min(table.SelectStartRow, table.SelectEndRow);
@@ -478,6 +507,13 @@ namespace XericUIEditor.XTable
int minC = Mathf.Min(table.SelectStartCol, table.SelectEndCol); int minC = Mathf.Min(table.SelectStartCol, table.SelectEndCol);
int maxC = Mathf.Max(table.SelectStartCol, table.SelectEndCol); int maxC = Mathf.Max(table.SelectStartCol, table.SelectEndCol);
// 扩展多选区域以包含合并源的全部跨度
if (table.IsMergeSource(minR, minC, out int msRS, out int msCS))
{
maxR = Mathf.Max(maxR, minR + msRS - 1);
maxC = Mathf.Max(maxC, minC + msCS - 1);
}
minR = Mathf.Clamp(minR, 0, rh.Length - 1); minR = Mathf.Clamp(minR, 0, rh.Length - 1);
maxR = Mathf.Clamp(maxR, 0, rh.Length - 1); maxR = Mathf.Clamp(maxR, 0, rh.Length - 1);
minC = Mathf.Clamp(minC, 0, cw.Length - 1); minC = Mathf.Clamp(minC, 0, cw.Length - 1);
@@ -492,10 +528,11 @@ namespace XericUIEditor.XTable
s_MultiSelectRangeColor); s_MultiSelectRangeColor);
} }
// 单选高亮(合并源用完整跨度)
float sx = tr.x + SumBefore(cw, sc) * xScale; float sx = tr.x + SumBefore(cw, sc) * xScale;
float sy = tr.y + SumBefore(rh, sr) * yScale; float sy = tr.y + SumBefore(rh, sr) * yScale;
float sw = cw[sc] * xScale; float sw = SumRange(cw, sc, sc + hlColSpan) * xScale;
float sh = rh[sr] * yScale; float sh = SumRange(rh, sr, sr + hlRowSpan) * yScale;
EditorGUI.DrawRect(new Rect(sx + 1, sy + 1, sw - 2, sh - 2), EditorGUI.DrawRect(new Rect(sx + 1, sy + 1, sw - 2, sh - 2),
s_SelectionColor); s_SelectionColor);
@@ -763,16 +800,31 @@ namespace XericUIEditor.XTable
padding = new RectOffset(4, 4, 2, 2) padding = new RectOffset(4, 4, 2, 2)
}; };
// Row 1: 坐标标签 | 输入框 | 应用按钮 // Row 1: 坐标标签 | 输入框 | 应用按钮 + 合并/拆分按钮
float btnW = 44; float actionBtnW = 50;
float row1Y = barRect.y + pad; float row1Y = barRect.y + pad;
float row2Y = barRect.y + rowH + pad + 4; float row2Y = barRect.y + rowH + pad + 4;
string cellLabel = table.GetSelectionText(); string cellLabel = table.GetSelectionText();
// 合并按钮(多选时显示)
bool showMerge = table.HasMultiSelection &&
(table.SelectStartRow != table.SelectEndRow ||
table.SelectStartCol != table.SelectEndCol);
// 拆分按钮(选中单元格是合并源时显示)
bool isMergeSource = table.IsMergeSource(table.SelectedRow,
table.SelectedCol, out _, out _);
float mergeBtnW = showMerge || isMergeSource ? actionBtnW : 0;
float unmergeBtnW = isMergeSource ? actionBtnW : 0;
// 坐标标签
GUI.Label(new Rect(barRect.x + 4, row1Y, 60, rowH), cellLabel, labelStyle); GUI.Label(new Rect(barRect.x + 4, row1Y, 60, rowH), cellLabel, labelStyle);
Rect inputRect = new Rect(barRect.x + 68, row1Y, barW - 68 - btnW - pad * 2, rowH);
// 输入框
float inputW = barW - 68 - 44 - 2 - mergeBtnW - unmergeBtnW - pad * 2 - 4;
Rect inputRect = new Rect(barRect.x + 68, row1Y, inputW, rowH);
// 回车提交(仅在 CellEditing 状态下)
if (s_State == EditorState.CellEditing && if (s_State == EditorState.CellEditing &&
Event.current.type == EventType.KeyDown && Event.current.type == EventType.KeyDown &&
Event.current.keyCode == KeyCode.Return) Event.current.keyCode == KeyCode.Return)
@@ -784,13 +836,51 @@ namespace XericUIEditor.XTable
GUI.SetNextControlName("XTableSceneEditInput"); GUI.SetNextControlName("XTableSceneEditInput");
s_EditText = GUI.TextField(inputRect, s_EditText, inputStyle); s_EditText = GUI.TextField(inputRect, s_EditText, inputStyle);
if (GUI.Button(new Rect(barRect.x + barW - btnW - pad, row1Y, btnW, rowH), // 应用按钮
"应用", btnStyle)) float rightX = barRect.x + barW - pad - 44;
if (GUI.Button(new Rect(rightX, row1Y, 44, rowH), "应用", btnStyle))
{ {
GUI.FocusControl(null); GUI.FocusControl(null);
ApplyCellEdit(table); ApplyCellEdit(table);
} }
// 合并按钮
if (showMerge)
{
var mergeStyle = new GUIStyle(btnStyle)
{
normal = { background = MakeTex(1, 1, new Color(0.15f, 0.3f, 0.65f, 0.8f)), textColor = Color.white },
hover = { background = MakeTex(1, 1, new Color(0.2f, 0.4f, 0.85f, 0.9f)), textColor = Color.white }
};
if (GUI.Button(new Rect(rightX - mergeBtnW - 2, row1Y, mergeBtnW, rowH), "合并", mergeStyle))
{
int minR = Mathf.Min(table.SelectStartRow, table.SelectEndRow);
int maxR = Mathf.Max(table.SelectStartRow, table.SelectEndRow);
int minC = Mathf.Min(table.SelectStartCol, table.SelectEndCol);
int maxC = Mathf.Max(table.SelectStartCol, table.SelectEndCol);
table.MergeCells(minR, minC, maxR - minR + 1, maxC - minC + 1);
table.RefreshView();
SceneView.RepaintAll();
}
}
// 拆分按钮
if (isMergeSource)
{
var unmergeStyle = new GUIStyle(btnStyle)
{
normal = { background = MakeTex(1, 1, new Color(0.65f, 0.25f, 0.15f, 0.8f)), textColor = Color.white },
hover = { background = MakeTex(1, 1, new Color(0.85f, 0.35f, 0.2f, 0.9f)), textColor = Color.white }
};
float unmergeX = showMerge ? rightX - mergeBtnW - unmergeBtnW - 4 : rightX - unmergeBtnW - 2;
if (GUI.Button(new Rect(unmergeX, row1Y, unmergeBtnW, rowH), "拆分", unmergeStyle))
{
table.UnmergeCells(table.SelectedRow, table.SelectedCol);
table.RefreshView();
SceneView.RepaintAll();
}
}
// Row 2: 样式命名空间下拉框 // Row 2: 样式命名空间下拉框
var nsLabelStyle = new GUIStyle(GUI.skin.label) var nsLabelStyle = new GUIStyle(GUI.skin.label)
{ {
@@ -800,11 +890,9 @@ namespace XericUIEditor.XTable
}; };
GUI.Label(new Rect(barRect.x + 4, row2Y, 36, rowH), "样式:", nsLabelStyle); GUI.Label(new Rect(barRect.x + 4, row2Y, 36, rowH), "样式:", nsLabelStyle);
// 获取当前命名空间
string currentNS = table.GetCellStyleNamespace( string currentNS = table.GetCellStyleNamespace(
table.SelectedRow, table.SelectedCol) ?? ""; table.SelectedRow, table.SelectedCol) ?? "";
// 构建下拉选项(StyleManager.GetAvailableNamespaces 已保证 "default" 在首位)
var namespaces = StyleManager.GetAvailableNamespaces(); var namespaces = StyleManager.GetAvailableNamespaces();
int currentIdx = namespaces.IndexOf(currentNS); int currentIdx = namespaces.IndexOf(currentNS);
if (currentIdx < 0) currentIdx = 0; if (currentIdx < 0) currentIdx = 0;
@@ -908,6 +996,46 @@ namespace XericUIEditor.XTable
float ry = (Event.current.mousePosition.y - tr.y) / yScale; float ry = (Event.current.mousePosition.y - tr.y) / yScale;
col = IndexFromCoord(rx, s_ColWidths); col = IndexFromCoord(rx, s_ColWidths);
row = IndexFromCoord(ry, s_RowHeights); row = IndexFromCoord(ry, s_RowHeights);
// 点击合并覆盖的单元格时,重定向到合并源
if (row >= 0 && col >= 0 && s_ActiveTable != null)
RedirectToMergeSource(ref row, ref col);
}
/// <summary>如果指定单元格被合并覆盖,重定向到合并源(锚点)</summary>
private static void RedirectToMergeSource(ref int row, ref int col)
{
var data = s_ActiveTable.TableData;
if (data == null) return;
XTableCoordinateUtility.CellToBlockCoordinate(
row, col, data.BlockSizeX, data.BlockSizeY,
out int blockRow, out int blockCol,
out int localRow, out int localCol);
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
if (!data.BlockMap.TryGetValue(zIndex, out XTableBlock block))
return;
var merge = block.GetMergeRedirect(localRow, localCol);
if (merge == null) return;
merge.GetRedirectTarget(out ulong targetBlockIndex, out int targetLocalRow, out int targetLocalCol);
if (merge.IsCrossBlock && data.BlockMap.TryGetValue(targetBlockIndex, out XTableBlock targetBlock))
{
// 跨块合并:从目标块的块坐标反算全局坐标
XTableBlockMapping.ZIndexToBlockCoord(targetBlockIndex,
out int targetBlockRow, out int targetBlockCol);
row = targetBlockRow * data.BlockSizeY + targetLocalRow;
col = targetBlockCol * data.BlockSizeX + targetLocalCol;
}
else
{
// 本地合并:源在同一块内,反算全局坐标
row = blockRow * data.BlockSizeY + targetLocalRow;
col = blockCol * data.BlockSizeX + targetLocalCol;
}
} }
#endregion #endregion
@@ -987,6 +1115,7 @@ namespace XericUIEditor.XTable
} }
else else
{ {
RedirectToMergeSource(ref row, ref col);
table.SelectCell(row, col); table.SelectCell(row, col);
} }
+105 -26
View File
@@ -229,12 +229,19 @@ namespace XericUI.XTable.Core
BlockMap[zIndex] = block; BlockMap[zIndex] = block;
} }
// 查找或创建此块的合并描述(相同源) // 计算本块内合并区域的局部起始和跨度
int localStartRow = Math.Max(0, startRow - blockRow * BlockSizeY);
int localStartCol = Math.Max(0, startCol - blockCol * BlockSizeX);
int blockEndRow = Math.Min((blockRow + 1) * BlockSizeY, startRow + rowSpan) - blockRow * BlockSizeY;
int blockEndCol = Math.Min((blockCol + 1) * BlockSizeX, startCol + colSpan) - blockCol * BlockSizeX;
// 查找或创建此块的合并描述
XTableMergeDescriptor descriptor = FindOrCreateMergeDescriptor(block, XTableMergeDescriptor descriptor = FindOrCreateMergeDescriptor(block,
zIndex == srcZIndex ? srcLocalRow : -1,
zIndex == srcZIndex ? srcLocalCol : -1,
srcZIndex, srcLocalRow, srcLocalCol, srcZIndex, srcLocalRow, srcLocalCol,
zIndex != srcZIndex); zIndex != srcZIndex,
localStartRow, localStartCol,
blockEndRow - localStartRow, blockEndCol - localStartCol,
rowSpan, colSpan);
descriptor.MergedCellSet.Add((localRow, localCol)); descriptor.MergedCellSet.Add((localRow, localCol));
} }
@@ -245,35 +252,41 @@ namespace XericUI.XTable.Core
/// 查找或创建合并描述 /// 查找或创建合并描述
/// </summary> /// </summary>
private XTableMergeDescriptor FindOrCreateMergeDescriptor( private XTableMergeDescriptor FindOrCreateMergeDescriptor(
XTableBlock block, int checkLocalRow, int checkLocalCol, XTableBlock block,
ulong srcZIndex, int srcLocalRow, int srcLocalCol, bool isCrossBlock) ulong srcZIndex, int srcLocalRow, int srcLocalCol, bool isCrossBlock,
int localStartRow, int localStartCol, int blockRowSpan, int blockColSpan,
int totalRowSpan, int totalColSpan)
{ {
// 查找已有描述 // 查找已有描述:匹配源坐标和跨块标记
for (int i = 0; i < block.MergeDescriptors.Count; i++) for (int i = 0; i < block.MergeDescriptors.Count; i++)
{ {
var desc = block.MergeDescriptors[i]; var desc = block.MergeDescriptors[i];
if (desc.MergeRowSpan > 0 && desc.MergeColSpan > 0) if (desc.IsCrossBlock == isCrossBlock &&
{ desc.SourceBlockIndex == srcZIndex &&
// 简化的同源判断:跨块引用共享 sourceBlockIndex desc.SourceLocalRow == srcLocalRow &&
if (isCrossBlock && desc.IsCrossBlock && desc.SourceBlockIndex == srcZIndex) desc.SourceLocalCol == srcLocalCol)
return desc; return desc;
}
} }
// 创建新描述 // 创建新描述,设置完整跨度信息
var newDesc = new XTableMergeDescriptor var newDesc = new XTableMergeDescriptor
{ {
IsCrossBlock = isCrossBlock, IsCrossBlock = isCrossBlock,
SourceBlockIndex = srcZIndex, SourceBlockIndex = srcZIndex,
SourceLocalRow = srcLocalRow, SourceLocalRow = srcLocalRow,
SourceLocalCol = srcLocalCol SourceLocalCol = srcLocalCol,
LocalStartRow = localStartRow,
LocalStartCol = localStartCol,
MergeRowSpan = totalRowSpan,
MergeColSpan = totalColSpan
}; };
block.MergeDescriptors.Add(newDesc); block.MergeDescriptors.Add(newDesc);
return newDesc; return newDesc;
} }
/// <summary> /// <summary>
/// 取消指定区域的合并 /// 取消指定坐标所在合并——同时处理"点击源坐标"和"点击被合并坐标"两种情况。
/// 遍历所有块,移除所有指向该源的合并描述。
/// </summary> /// </summary>
public void UnmergeCells(int startRow, int startCol) public void UnmergeCells(int startRow, int startCol)
{ {
@@ -284,15 +297,43 @@ namespace XericUI.XTable.Core
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol); ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
if (!BlockMap.TryGetValue(zIndex, out XTableBlock block)) // 1) 从这个单元格所在的块开始:移除包含此坐标的合并描述(被合并格)
return; if (BlockMap.TryGetValue(zIndex, out XTableBlock block))
// 移除包含此单元格的所有合并描述
for (int i = block.MergeDescriptors.Count - 1; i >= 0; i--)
{ {
if (block.MergeDescriptors[i].Contains(localRow, localCol)) for (int i = block.MergeDescriptors.Count - 1; i >= 0; i--)
{ {
block.MergeDescriptors.RemoveAt(i); if (block.MergeDescriptors[i].Contains(localRow, localCol))
block.MergeDescriptors.RemoveAt(i);
}
}
// 2) 遍历所有块:移除源坐标为此单元格的合并描述(合并源 / 锚点)
// 处理非跨块和跨块两种情况
foreach (var kv in BlockMap)
{
var b = kv.Value;
if (b.MergeDescriptors.Count == 0) continue;
for (int i = b.MergeDescriptors.Count - 1; i >= 0; i--)
{
var desc = b.MergeDescriptors[i];
// 非跨块:源在同一个块内 → 直接比较本地坐标
if (!desc.IsCrossBlock &&
desc.SourceLocalRow == localRow &&
desc.SourceLocalCol == localCol &&
kv.Key == zIndex)
{
b.MergeDescriptors.RemoveAt(i);
}
// 跨块:源在另一个块 → 比较 SourceBlockIndex + 源本地坐标
else if (desc.IsCrossBlock &&
desc.SourceBlockIndex == zIndex &&
desc.SourceLocalRow == localRow &&
desc.SourceLocalCol == localCol)
{
b.MergeDescriptors.RemoveAt(i);
}
} }
} }
} }
@@ -301,9 +342,47 @@ namespace XericUI.XTable.Core
#region 查询方法 #region 查询方法
/// <summary> /// <summary>判断指定单元格是否被合并覆盖(非源,会被重定向)</summary>
/// 判断指定块是否存在 public bool IsCellMerged(int row, int col)
/// </summary> {
XTableCoordinateUtility.CellToBlockCoordinate(
row, col, BlockSizeX, BlockSizeY,
out int blockRow, out int blockCol,
out int localRow, out int localCol);
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
if (!BlockMap.TryGetValue(zIndex, out XTableBlock block)) return false;
return block.GetMergeRedirect(localRow, localCol) != null;
}
/// <summary>判断指定单元格是否为合并源(锚点),并返回合并跨度</summary>
public bool IsMergeSource(int row, int col, out int rowSpan, out int colSpan)
{
rowSpan = 1; colSpan = 1;
XTableCoordinateUtility.CellToBlockCoordinate(
row, col, BlockSizeX, BlockSizeY,
out int blockRow, out int blockCol,
out int localRow, out int localCol);
ulong thisZIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
foreach (var kv in BlockMap)
{
foreach (var desc in kv.Value.MergeDescriptors)
{
ulong srcBlockIdx = desc.IsCrossBlock ? desc.SourceBlockIndex : kv.Key;
if (srcBlockIdx == thisZIndex &&
desc.SourceLocalRow == localRow &&
desc.SourceLocalCol == localCol)
{
rowSpan = desc.MergeRowSpan;
colSpan = desc.MergeColSpan;
return true;
}
}
}
return false;
}
/// <summary>判断指定块是否存在</summary>
public bool HasBlock(int blockRow, int blockCol) public bool HasBlock(int blockRow, int blockCol)
{ {
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol); ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
@@ -310,6 +310,13 @@ namespace XericUI.XTable.Rendering.Component
MarkDirty(TableDirtyType.DataChanged); MarkDirty(TableDirtyType.DataChanged);
} }
/// <summary>判断指定单元格是否被合并覆盖(非源,会被重定向)</summary>
public bool IsCellMerged(int row, int col) => TableData.IsCellMerged(row, col);
/// <summary>判断指定单元格是否为合并源(锚点),并返回合并跨度</summary>
public bool IsMergeSource(int row, int col, out int rowSpan, out int colSpan)
=> TableData.IsMergeSource(row, col, out rowSpan, out colSpan);
/// <summary>在末尾追加一行,默认行高 40</summary> /// <summary>在末尾追加一行,默认行高 40</summary>
public void AddRow(float height = 40f) public void AddRow(float height = 40f)
{ {
@@ -738,15 +745,28 @@ namespace XericUI.XTable.Rendering.Component
{ {
for (int c = sc; c < ec && c < m_ColWidths.Length; c++) for (int c = sc; c < ec && c < m_ColWidths.Length; c++)
{ {
// 跳过被合并覆盖的单元格
if (TableData.IsCellMerged(r, c)) continue;
float cellX = GetColLeftX(c); float cellX = GetColLeftX(c);
float cellY = -GetRowTopY(r); float cellY = -GetRowTopY(r);
float cellW = m_ColWidths[c]; float cellW = m_ColWidths[c];
float cellH = m_RowHeights[r]; float cellH = m_RowHeights[r];
// 合并源:扩展尺寸
if (TableData.IsMergeSource(r, c, out int mergeRS, out int mergeCS))
{
for (int i = 1; i < mergeCS && c + i < m_ColWidths.Length; i++)
cellW += m_ColWidths[c + i];
for (int i = 1; i < mergeRS && r + i < m_RowHeights.Length; i++)
cellH += m_RowHeights[r + i];
}
XTableCellData data = TableData.GetCell(r, c); XTableCellData data = TableData.GetCell(r, c);
string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace)) string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace))
? data.StyleNamespace : ns; ? data.StyleNamespace : ns;
// 多选高亮 // 多选 / 单选高亮
if (IsInSelectionRange(r, c)) if (IsInSelectionRange(r, c))
{ {
var selImg = m_Assembler.GetImage("cell_multiselect"); var selImg = m_Assembler.GetImage("cell_multiselect");
@@ -763,13 +783,13 @@ namespace XericUI.XTable.Rendering.Component
selImg.Image.color = selectionColor; selImg.Image.color = selectionColor;
} }
// 水平网格线(单元格底部) // 水平网格线(合并区域底部)
var hLine = m_Assembler.GetImage("cell_hline"); var hLine = m_Assembler.GetImage("cell_hline");
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH); hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth); hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth);
hLine.Image.color = borderColor; hLine.Image.color = borderColor;
// 垂直网格线(单元格右侧) // 垂直网格线(合并区域右侧)
var vLine = m_Assembler.GetImage("cell_vline"); var vLine = m_Assembler.GetImage("cell_vline");
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY); vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY);
vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH); vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH);
@@ -802,10 +822,23 @@ namespace XericUI.XTable.Rendering.Component
{ {
for (int c = sc; c < ec && c < m_ColWidths.Length; c++) for (int c = sc; c < ec && c < m_ColWidths.Length; c++)
{ {
// 跳过被合并覆盖的单元格
if (TableData.IsCellMerged(r, c)) continue;
float cellX = GetColLeftX(c); float cellX = GetColLeftX(c);
float cellY = -GetRowTopY(r); float cellY = -GetRowTopY(r);
float cellW = m_ColWidths[c]; float cellW = m_ColWidths[c];
float cellH = m_RowHeights[r]; float cellH = m_RowHeights[r];
// 合并源:扩展尺寸
if (TableData.IsMergeSource(r, c, out int mergeRS, out int mergeCS))
{
for (int i = 1; i < mergeCS && c + i < m_ColWidths.Length; i++)
cellW += m_ColWidths[c + i];
for (int i = 1; i < mergeRS && r + i < m_RowHeights.Length; i++)
cellH += m_RowHeights[r + i];
}
XTableCellData data = TableData.GetCell(r, c); XTableCellData data = TableData.GetCell(r, c);
string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace)) string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace))
? data.StyleNamespace : ns; ? data.StyleNamespace : ns;