【问题标题】:Find Max Line Count for Unity UI.Text查找 Unity UI.Text 的最大行数
【发布时间】:2018-05-21 16:47:35
【问题描述】:

我正在尝试确定UI.Text 的最大行数,其中VerticalOverflow 设置为truncate,以便以后可以使用行数。到目前为止,我想出了这段代码,这显然是不切实际的,甚至可能是危险的:

/// <summary>
///     Returns the max visible line count of a UI.Text component. The text's vertical
///     overflow must be set to truncate or this method will return 0.
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static int GetMaxLineCount(Text text)
{
    if (text == null || text.verticalOverflow != VerticalWrapMode.Truncate) return 0;
    var textBackup = text.text;
    var lineCount = 0;
    text.text = "";
    while (true)
    {
        text.text += "\n";
        Canvas.ForceUpdateCanvases();
        var nextLineCount = text.cachedTextGenerator.lineCount;
        if (lineCount == nextLineCount) break;
        lineCount = nextLineCount;
    }
    text.text = textBackup;
    return lineCount;
}

有没有更好的方法来(预先)确定 UI.Text 组件的最大行数(在底部截断文本之前)?

【问题讨论】:

  • 几年前我曾经尝试过制作类似的东西,但后来放弃了。我没有再次尝试过,但我现在认为您还需要在计算中考虑 Text 字体的大小。请不要问我怎么做,因为我不知道,但你需要这样做。字体大小、屏幕高度/宽度和文本长度。
  • 摸索涉及字体大小的计算已被证明过于不精确。 text.cachedTextGenerator.lineCount 是一个不错的开始,但文本需要在返回最大行数之前用行完全填充。

标签: c# user-interface unity3d text


【解决方案1】:

你可以试试这样的

TextGenerator textGenenerator = new TextGenerator(); TextGenerationSettings generationSettings = text.GetGenerationSettings(text.rectTransform.rect.size); float height = textGenenerator.GetPreferredHeight(newText, generationSettings);

您可以在此处阅读更多信息https://docs.unity3d.com/ScriptReference/TextGenerator.html

---与您的代码相关的注释---

您调用 Canvas.ForceUpdateCanvases() 会进行大量调用以仅更新一个 Text 并且在运行该代码时检查器设置错误,如果 Text 允许无限行,您可能会陷入无限循环。

【讨论】:

  • Canvas.ForceUpdateCanvases() 让我担心,因为如果渲染大量 UI,它可能会产生很大的影响。然而,由于文本对于文本网格来说太大,文本可能会在无限循环之前崩溃。
【解决方案2】:

感谢@Neven 为我指明了正确的方向! TextGenerator 可用于计算后台的最大行数。优点是Canvas.ForceUpdateCanvases()不再需要调用,原始Text也不会改变。它仍然需要一个循环来计算最大线,但它比我的第一种方法要好得多......

public static int GetMaxLineCount(Text text)
{
    var textGenerator = new TextGenerator();
    var generationSettings = text.GetGenerationSettings(text.rectTransform.rect.size);
    var lineCount = 0;
    var s = new StringBuilder();
    while (true)
    {
        s.Append("\n");
        textGenerator.Populate(s.ToString(), generationSettings);
        var nextLineCount = textGenerator.lineCount;
        if (lineCount == nextLineCount) break;
        lineCount = nextLineCount;
    }
    return lineCount;
}

【讨论】:

  • 您在评论中提到“摸索涉及字体大小的计算已被证明过于不精确。”,我认为如果您使用 TextGenerator 它就足够精确并且不需要太多性能。我在想的是当有一行(rowHeight)和有两行(twoRowHeight)时计算高度//rowDistance = twoRowHeight-2*rowHeight; ("n" 是行数) 然后你可以写 n*rowHeight+(n-1)rowDistance
  • 我建议你做一个实验,计算你原来的最大行数(因为我们知道这是 100% 精确的),然后使用这种方法,做一个循环逐渐增加最大高度和记录所有结果,然后比较它们以查看计算何时关闭。我认为你会得到很好的结果(我在网上读到 Unity 内部也使用 TextGenerator,但不能保证)。如果这不起作用,您可以扩展精度,计算 3 行的高度,以便计算上下填充。
  • 我还是明白这不是很好,但是Unity对这方面的支持真的很烂,也请做实验并在这里发布结果,我认为这种方法很精确,更何况它只是一个与原始方式相比,开销的一小部分。
  • @NevenIgnjic 就我的目的而言,上面的方法很好。只有在文本区域大小发生变化时才需要调用它,否则它会可靠地报告行数。如果我在 UI.Text 限制方面有其他问题,那么我会检查 TextMeshPro 是否可以帮助我。他们将把 TMPro 集成到 Unity 2018 中,这是一个很有前途的文本支持解决方案。
猜你喜欢
  • 2015-07-11
  • 2019-11-14
  • 1970-01-01
  • 2021-01-04
  • 2016-04-06
  • 2018-02-07
  • 2012-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多