跳到正文
0:00 / 0:00
已成形

UGUI 布局与 SuperScrollView 列表实战

3 分钟

AI 摘要

解决Unity UI布局适配与动态交互痛点,涵盖RectTransform锚点计算、SuperScrollView列表刷新时序陷阱、LayoutGroup隐藏节点动效处理及进度条尺寸匹配策略,提供组件级细节优化方案。

UI 布局是「看起来简单、出错很频繁」的一块。这篇整理 RectTransform 基础、LayoutGroup 与动效的配合、SuperScrollView 的刷新顺序,以及若干组件级细节。

一、RectTransform 基础:锚点与四角

  • 四个锚点的计算要熟练 —— 它决定了控件在不同分辨率下的拉伸与定位行为。
  • 取世界坐标下的四角:
Vector3[] corners = new Vector3[4];
targetRectTransform.GetWorldCorners(corners);
// corners[0] 左下, corners[1] 左上, corners[2] 右上, corners[3] 右下
  • Image.SetNativeSize() 可以把图片恢复为原始大小。

二、SuperScrollView 的四条经验

SuperScrollView(LoopListView2)在处理大量列表项时非常高效,但有几个反复踩的坑。

1. item 必须有 RectTransform 组件。

2. 切换数据时图片加载错误(例如背包切页签)

现象:切页签后 item 上的图片加载错乱。解法:用协程延迟刷新,等布局稳定后再刷新图片。

3. 不要直接 InitListView 后就完事

直接 InitListView 容易让 item 的动画失效。推荐顺序:

loopListView.InitListView(0, ItemRender);   // 先传 0
loopListView.SetListItemCount(_enemyList.Count);
loopListView.RefreshAllShownItem();

4. SetListItemCount 与 RefreshAllShownItem 不要同时使用

前者本身就包含了「设置数量 + 刷新数量」的逻辑,两者叠加会重复刷新(必要时需要自己改内部实现)。

三、LayoutGroup 与「逐个入场」动效

LayoutGroup 默认不计算隐藏节点的布局。如果想给列表做「逐个淡入」的动效,有个可行的办法:

  1. 在 content 上挂 CanvasGroup,把 alpha 设为 0;
  2. 等 item 都加载完(激活状态)后,LayoutRebuilder.ForceRebuildLayoutImmediate(RectTransform) 重新计算布局;
  3. 遍历 content 依次失活所有 item;
  4. 禁用 LayoutGroup 和 ContentSizeFitter;
  5. 把 CanvasGroup.alpha 设为 1;
  6. 依次激活所有 item(期间可以做逐个出现的动效);
  7. 最后按需重新启用 LayoutGroup 和 ContentSizeFitter。

示例:

IEnumerator LoadChooseItem(params int[] param)
{
    canvasGroup.alpha = 0;
    MyFunction.DestroyAllChildren(chooseItemContent);

    var list = GameplayManager.Instance.GetGameplayConfigIdList();
    foreach (var gamePlayId in list)
    {
        var newChooseItem = Instantiate(chooseItem, chooseItemContent);
        newChooseItem.gameObject.SetActive(true);
        var playModeData = GameplayManager.Instance.GetPlayModeData(gamePlayId);
        newChooseItem.SetData(playModeData);
        if (param.Length > 0 && param[0] == gamePlayId)
        {
            isRedirected = true;
            newChooseItem.OnClick();
        }
    }

    LayoutRebuilder.ForceRebuildLayoutImmediate(chooseItemContent as RectTransform);
    layoutGroup.enabled = false;
    sizeFitter.enabled = false;

    foreach (Transform trans in chooseItemContent)
        trans.gameObject.SetActive(false);
    canvasGroup.alpha = 1;

    foreach (Transform trans in chooseItemContent)
    {
        trans.gameObject.SetActive(true);
        yield return new WaitForSeconds(_actualItemShowInterval);
    }

    layoutGroup.enabled = true;
    sizeFitter.enabled = true;
}

四、Toggle 的回调陷阱

使用 Toggle 时,不要在 onValueChanged 的回调里调用 ToggleGroup.ActiveToggles() —— 因为 toggle 的关闭和打开会分别调用该回调,可能导致 toggle 状态判断错误。

五、进度条:fillAmount 不匹配时怎么办

设置进度条时,如果原图与效果图的尺寸不匹配,用 fillAmount 会出现异常(填充区域对不上)。此时可以考虑用遮罩或 Shader 来实现。

六、DOTween 的 Ease 速查

DOTween 的 Ease 枚举里,常用缓动:

枚举 效果
Ease.OutQuad(值 6) 先快后慢
Ease.InQuad 先慢后快
Ease.InOutQuad 两头慢、中间快
Ease.Linear 匀速

七、指针事件接口

实现 IPointerDownHandler 等接口即可接收对应的指针事件(配合 Graphic Raycaster)。前提仍是目标的 Raycast Target 已开启。

小结

  • 锚点决定适配行为,GetWorldCorners 四角顺序是「左下、左上、右上、右下」。
  • SuperScrollView 记住三点:item 要有 RectTransform、刷新顺序是「先 0 → 设数量 → RefreshAllShownItem」、SetListItemCount 与 RefreshAllShownItem 不同时用。
  • LayoutGroup 不算隐藏节点,配动效要走「先构建 → 全失活 → 逐个激活」的流程。
  • Toggle 回调里别查 ActiveToggles;进度条尺寸不匹配就别硬用 fillAmount。

相关:Unity 渲染与排序:Layer、Sorting Layer 与 UI 绘制顺序

这是一条笔记,不是成稿文章。它可能不完整、可能有错,也可能过段时间就被我推翻。 想看成体系的文章,去 Blog。

linked from1 处引用了这篇