将多行文本放入动态改变大小的节点
Fitting multi-line text into a dynamically size-changing node
多行自动输入文本框 class(使用 SKNode 作为父级)基本上使用 2 个元素创建:
- 充当文本框框架和背景的 SKSpriteNode image/texture 持有者。
- 一个 NSMutableArray,包含有限数量(行)的 NSString,每个 NSString 都有固定的字符长度。
修改此文本框 class 以便它可以用任何框架宽度和高度进行初始化后,我意识到我没有对 NSMutableArray 进行编程以自动更改其内容以使其非常适合在后台节点内(也涉及一些填充)。所以在这里我想知道如何做到这一点,因为 NSString 只能 return 字符计数而不是每个字符串的宽度和高度(点可能以某种方式帮助我创建字符约束)。
现在,NSMutableArray 使用每个 NSString 的硬编码最大字符数和整个数组的最大行数(现在是 5 行,当达到该限制时,一个新的 "page"/array 是创建)。这迫使我每次更改背景节点框架大小时都必须手动重新调整这些参数,这违背了 class 允许背景框架更改的目的。
事情是,我试图以这样的方式解决这个问题,即当我在 github 上 post 这个 class 时,我希望解决方案考虑任何 fontName & 字体大小。
解决这个问题我有哪些选择?
我做过类似的事情。它不能 100% 满足您的需求,但应该足够相似。它使用一个根节点,从那里,它将使用 NSString
的数组构建 multi-line 文本,该数组又将用于构建 SKLabelNode
。
我将概述我所做的事情。我还应该说,当设置新文本时,我只 运行 这个。换句话说,我不会招致每帧都导出信息的惩罚。只有一次。
通用步骤为:
- 您将遍历文本字符串中的每个字符。请注意,我这样做是因为我的代码支持自动换行以及其他对齐功能。所以对我来说,我想要那种程度的控制。因为这只是在创建时完成的,所以我可以接受开销。如果你不想自动换行,你总是可以创建一个单词数组并从那里开始工作。
- 当您遍历每个字符时,您将生成一个行数组。数组中的每一行都是适合您的框架的行。现在让我们不要担心垂直约束。所以在这里我们主要担心宽度。对于当前行,您迭代的每个字符都将添加到当前行。对于这个潜在的行字符串,您将使用
NSString
的 sizeWithAttributes
,它是为您的字体配置的。例如,在我的代码中,它是一个 NSDictionary
,其中包含:NSFontAttributeName : [UIFont fontWithName:self.fontName size:self.size]
。这将用于检查宽度,如果该宽度超过框架宽度,则您超过了运行线。
因此代码可能类似于:
size = [line sizeWithAttributes:attributes];
if (size.width > maxTextWidth) {
needNewline = YES;
}
- 如果超过运行行,需要判断是否自动换行。如果是,则只需将当前行(减去一个字符)添加到行数组即可。如果不是,则将 p运行e 从当前行的最后一个单词中删除,然后将其添加到行数组中。
- 棘手的部分是处理空白和处理 non-word 包装溢出。我没有解决空白问题,但您需要在代码中充分考虑这一点。此外,您还需要考虑前导像素等因素。
一旦你有了你的行数组,你就可以创建你的 children SKLabelNode
s。我将它们添加到根,这样我就可以将组移动到任何需要的位置。
这里真正的关键是线条数组的生成。
多行自动输入文本框 class(使用 SKNode 作为父级)基本上使用 2 个元素创建:
- 充当文本框框架和背景的 SKSpriteNode image/texture 持有者。
- 一个 NSMutableArray,包含有限数量(行)的 NSString,每个 NSString 都有固定的字符长度。
修改此文本框 class 以便它可以用任何框架宽度和高度进行初始化后,我意识到我没有对 NSMutableArray 进行编程以自动更改其内容以使其非常适合在后台节点内(也涉及一些填充)。所以在这里我想知道如何做到这一点,因为 NSString 只能 return 字符计数而不是每个字符串的宽度和高度(点可能以某种方式帮助我创建字符约束)。
现在,NSMutableArray 使用每个 NSString 的硬编码最大字符数和整个数组的最大行数(现在是 5 行,当达到该限制时,一个新的 "page"/array 是创建)。这迫使我每次更改背景节点框架大小时都必须手动重新调整这些参数,这违背了 class 允许背景框架更改的目的。
事情是,我试图以这样的方式解决这个问题,即当我在 github 上 post 这个 class 时,我希望解决方案考虑任何 fontName & 字体大小。
解决这个问题我有哪些选择?
我做过类似的事情。它不能 100% 满足您的需求,但应该足够相似。它使用一个根节点,从那里,它将使用 NSString
的数组构建 multi-line 文本,该数组又将用于构建 SKLabelNode
。
我将概述我所做的事情。我还应该说,当设置新文本时,我只 运行 这个。换句话说,我不会招致每帧都导出信息的惩罚。只有一次。
通用步骤为:
- 您将遍历文本字符串中的每个字符。请注意,我这样做是因为我的代码支持自动换行以及其他对齐功能。所以对我来说,我想要那种程度的控制。因为这只是在创建时完成的,所以我可以接受开销。如果你不想自动换行,你总是可以创建一个单词数组并从那里开始工作。
- 当您遍历每个字符时,您将生成一个行数组。数组中的每一行都是适合您的框架的行。现在让我们不要担心垂直约束。所以在这里我们主要担心宽度。对于当前行,您迭代的每个字符都将添加到当前行。对于这个潜在的行字符串,您将使用
NSString
的sizeWithAttributes
,它是为您的字体配置的。例如,在我的代码中,它是一个NSDictionary
,其中包含:NSFontAttributeName : [UIFont fontWithName:self.fontName size:self.size]
。这将用于检查宽度,如果该宽度超过框架宽度,则您超过了运行线。
因此代码可能类似于:
size = [line sizeWithAttributes:attributes];
if (size.width > maxTextWidth) {
needNewline = YES;
}
- 如果超过运行行,需要判断是否自动换行。如果是,则只需将当前行(减去一个字符)添加到行数组即可。如果不是,则将 p运行e 从当前行的最后一个单词中删除,然后将其添加到行数组中。
- 棘手的部分是处理空白和处理 non-word 包装溢出。我没有解决空白问题,但您需要在代码中充分考虑这一点。此外,您还需要考虑前导像素等因素。
一旦你有了你的行数组,你就可以创建你的 children SKLabelNode
s。我将它们添加到根,这样我就可以将组移动到任何需要的位置。
这里真正的关键是线条数组的生成。