2014 年 2 月 11 日
教程:文本定位方法
在基本层面上,在 Corona SDK 中创建和定位文本很简单:只需在指定字体大小的所需位置创建对象即可。例如
1 |
local myText = display.newText( "Hello World", 200, 200, native.systemFont, 16 ) |
但是,当您需要以创造性的方式定位/对齐文本时,事情会变得更加复杂。在本教程中,我们将检查 Corona 通过 display.newText() 生成的实际显示对象,以便您可以理解并实现高级定位和对齐。
基础知识
在底层,Corona 会获取您传递给 display.newText() API 的信息,并生成一个图像,像任何其他显示对象一样渲染到纹理内存。由于 Corona SDK 使用操作系统的字体渲染,因此字体在设备和 Corona 模拟器之间,特别是在 Windows 和 OS X 之间可能会渲染不同。
单行方法
display.newText() 最基本的用法是 单行方法。使用此方法,您只需将文本字符串输出到屏幕上。一旦它被 Corona 渲染,理论上的“边界框”(用绿线表示)将精确地适合文本显示对象周围
关于屏幕位置,这个“框”的 x
和 y
基于它的中心点。当然,您可以通过这个中心点定位任何文本对象,但是如果您要构建一系列文本对象,例如统计屏幕上的标签,您可能希望将它们全部左对齐到垂直“引导线”。这可以使用 锚点 来完成,其中,关于 x
位置,锚点 0
表示对象的最左点,0.5
表示中心 x
点,1
表示最右点。类似的概念适用于 y
锚点,其中 y
锚点 0
表示对象的顶部,0.5
表示垂直中间,1
表示对象的底部。
让我们检查一个基本示例
1 2 3 4 5 6 |
local myText = display.newText( "Hello World", 0, 0, native.systemFont, 16 ) myText:setFillColor( 0, 0, 0 ) myText.anchorX = 0 myText.x = 10 myText.y = 100 |
因为 anchorX
值设置为 0
(左边缘),并且 x
值设置为 10
,所以此代码块将文本定位为其左边缘位于内容区域垂直 0
点右侧 10 个点的位置。但请记住,您不是“对齐文本”,而是定位其边界框(这一点在后面会变得更重要)。
多行方法
为了进行更高级的对齐,您可以利用多行方法。在这种情况下,您将一个选项表传递给 display.newText() 调用。这些选项中的大多数都模仿了上面概述的“简写”单行声明中的选项,但还有三个附加属性扩展了对齐的可能性:width
、height
和 align
。
宽度
此属性指定多行“边界框”的宽度(以像素为单位)。这类似于在 Photoshop 或 Illustrator 等图形应用程序中绘制一个灵活的文本框,无论您在框中输入多少文本,文本都将在其边界内换行。正如预期的那样,如果一个单词太长而无法容纳在该行中剩余的宽度,它将换行到下一行。
高度
如果指定,文本将在此值(以像素为单位)处裁剪。如果您想要文本框的“无限制”高度,请将此值设置为 0
,并且框的高度将根据其中的文本量进行调整。但是,它永远不会超过设备的最大纹理尺寸限制。
对齐
这指定了当提供 width
参数时文本的对齐方式。默认值为 "left"
。有效值为 "left"
、"center"
或 "right"
。我们将在稍后详细讨论这一点。
对齐原则
尽管使用多行方法创建单行文本可能看起来不直观,但让我们从 Corona 的角度探讨其优势
1 2 3 4 5 6 7 8 9 10 11 12 |
local options = { text = "Hello World", x = display.contentCenterX, y = display.contentCenterY, fontSize = 24, width = 200, height = 0, align = "left" } local textBox = display.newText( options ) textBox:setFillColor( 0, 0, 0 ) |
因为字符串 Hello World 在默认系统字体中以 24 大小适合 200 像素的宽度,所以它不会换行到第二行。因此,此代码在视觉上产生单行文本。但是,尽管它可能看起来与第一个示例相同,但重要的是要理解“边界框”现在是 200 像素宽,而不是您在屏幕上看到的实际文本的像素宽度
通过这种方式,您可以构建一系列固定宽度的文本框,并以更统一的方式定位它们,而不是处理通过单行方法产生的各种文本对象大小。
想要右对齐文本吗?只需将 align
参数更改为 "right"
即可…
或者您可以将其更改为 "center"
…
除了这些灵活的对齐选项外,多行方法的另一个优点是,它允许您更改 .text
属性的值,并且如果新字符串更长或更短,则文本框仍保持固定宽度,文本不会意外移动。相比之下,在单行模式下,如果您通过其中心点定位文本对象并更改文本字符串,则该对象可能不会按照您的预期对齐。
多行
当然,多行模式也支持多行!让我们看看它在三种不同对齐选项中的外观
“左对齐”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
local myText = [[这是一个很长的多行字符串,我们在其中随机 插入一些空白 行 文本。]] local options = { text = myText, x = display.contentCenterX, y = display.contentCenterY, width = 200, height = 300, fontSize = 24, align = "left" } local textField = display.newText( options ) textField:setFillColor( 0, 0, 0 ) |
“居中”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
local myText = [[这是一个很长的多行字符串,我们在其中随机 插入一些空白 行 文本。]] local options = { text = myText, x = display.contentCenterX, y = display.contentCenterY, width = 200, height = 300, fontSize = 24, align = "center" } --使用指定的选项输出文本框 local textField = display.newText( options ) textField:setFillColor( 0, 0, 0 ) |
“右对齐”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
local myText = [[这是一个很长的多行字符串,我们在其中随机 插入一些空白 行 文本。]] local options = { text = myText, x = display.contentCenterX, y = display.contentCenterY, width = 200, height = 300, fontSize = 24, align = "right" } --使用指定的选项输出文本框 local textField = display.newText( options ) textField:setFillColor( 0, 0, 0 ) |
如您所见,align
选项会影响文本在框内的位置。在所有这些示例中,框的高度定义为 300
。 如果您将 height
设置为 0
,则边界框将与文本的实际高度匹配。 但是,这可能会影响垂直对齐,具体取决于框的 y
锚点设置。 此外,虽然 height
设置为 0
会创建一个“无限”高度的文本框,但创建的文本永远不会超过设备的纹理大小限制。 如果您将大量文本放入单个文本框中,则这是一个需要注意的重要限制。
关于多行的话题…
在 Lua 中,关于如何在字符串中添加换行符存在一些混淆。虽然 Lua 支持传统的双引号 ("..."
) 或单引号 ('...'
),但它也支持通过 [[...]]
声明进行多行显示。 因此,您可以使用此方法**或**引号内的 Unix “换行”字符 (\n
)
1 2 3 4 5 6 7 |
longString = [[这是一个很长的 字符串 包含多个 换行符。]] --或者... longString = "这是一个很长的\n字符串\n包含多个\n换行符。" |
请注意,如果您尝试使用 Corona 的单行方法输入多行,则会忽略换行符。
总结
希望本教程向您展示了一些在 Corona SDK 中对齐文本的有用技巧。 通过单行方法和功能更强大的多行方法,几乎任何对齐场景都可以通过几行代码实现。
JCH
发布于 23:58, 2 月 11 日不幸的是,在文本中更改颜色(例如,突出显示搜索结果)不是很简单。
如果有一个 “htmlText” 选项,允许诸如颜色或属性(粗体、斜体)之类的“简单”更改,会怎么样?
罗布·米拉奇
发布于 15:20, 2 月 12 日Corona SDK 的 display.newText() 不是为处理富文本而设计的。 我们建议您将一个小的 HTML/CSS 文件写入临时目录,并在需要更样式化的文本时使用 native.newWebview 显示它。 已经有一些社区项目支持将更多富文本作为显示对象。 您必须在论坛中搜索它。
JCH_APPLE
发布于 22:21, 2 月 12 日谢谢。 希望它会在某天被包含进来,这将有很大帮助。
大卫·格罗斯
发布于 00:28, 2 月 2 日我创建了一个复杂的文本渲染模块,它允许许多 HTML 格式,例如粗体、斜体,甚至是某种样式。 我将它用于书籍。 速度非常快。 如果您愿意,可以向我咨询。
安德里亚
发布于 09:20, 1 月 15 日我是 corona 的新手,
我正在尝试在 composer 中创建一个视图,其中包含
一个带有来自本地数据库的动态文本的滚动视图
标题(短,不换行)
文本(短,不换行)
文本(短,不换行)
长文本(长,换行)
我尝试了 webview,很容易动态创建网页并在视图上显示它,但不幸的是,当我更改视图时,webview 不支持过渡,所以我很困惑……创建一个如上所述的滚动视图真的那么困难吗?
如果有人有可用的示例,我将非常感激..
谢谢
大卫·梅克萨
发布于 00:02, 2 月 12 日JCH,一个想法:您可以在 HTML 中生成搜索结果,并使用 webview 来显示它。
JCH
发布于 05:50, 2 月 12 日我会尝试,但我的文本显示在表格视图中,我不确定表格视图是否可以“容纳” webView
罗布·米拉奇
发布于 15:20, 2 月 12 日不幸的是,TableView 不能容纳 webView。
勒格
发布于 00:14, 2 月 12 日不使用系统的字体渲染怎么样? 这样,应用程序将在所有平台上以相同的方式工作。
JCH
发布于 05:46, 2 月 12 日您有这种技术的示例吗?
海利欧斯·那喀索斯
发布于 16:08, 2 月 12 日感谢您关于文本 TopLeftReferencePoint 的“SCORING”定位的提示。 这真的很有帮助 🙂
巴勃罗·伊西德罗
发布于 04:01, 2 月 13 日很棒的教程!
史蒂夫
发布于 13:18, 2 月 13 日当然,他们不会告诉您,并且任何地方都没有介绍的是,您可以在 newText 对象中放入多少文本是有限制的,超过此限制,它将不会显示或抛出错误。 如果您遇到此问题,诀窍是将多个较小的块循环到一个显示对象中,将下一个文本块放置在前一个文本块之后
亨德里克斯
发布于 22:45, 2 月 13 日我最近在我的一个游戏中使用了这个功能,并使用了自定义字体,它在 IOS 上运行良好,我也在 galaxy 4s 上进行了测试,它在那里也渲染得很好(但不确定这如何适用于其他显示器)。
好教程,罗布,一如既往 🙂
primoz.cerar
发布于 23:54, 2 月 13 日我玩过文本很多次,我有一个问题。
是否可以设置值,以便在宽度处裁剪文本而不是换行。 我有一种情况,我必须在宽度处裁剪文本(如果文本太长),但我不想为了确保只显示一行而摆弄高度,并且换行会更快地转到新行,因此在末尾可能会有一些空间用于几个字母。
我是否最好使用容器来解决这个问题?
罗布·米拉奇
发布于 11:39, 2 月 15 日容器是解决此问题的好选择。
sunmils
发布于 12:10, 2 月 17 日您还可以使用我的文本包装器类进行自动字体大小调整,以便文本始终适合您给定的尺寸,而与其长度无关。 您可以在新的代码交换中找到它。
charlie_82
发布于 05:24, 2 月 18 日谢谢! 这是一个很棒的 SDK!
MartinW
发布于 20:46, 3 月 6 日谢谢你,罗布,我已经在我的应用程序中使用了多行代码,这正是我想要的!
普拉文
发布于 03:22, 5 月 28 日谢谢罗布。 多行功能非常棒,尤其是在字符大小变化很大的 Unicode 方面。
但是,我有一个抱怨,文本渲染会被裁剪到“高度”。 这会导致显示一行的一部分。 这会造成不良的视觉效果。
如果可以知道哪个字符将最终成为最后完全渲染的行中的最后一个字符,那就太好了。 那么我就可以将文本修剪到正确的长度,并添加一个“…”并使用 newText() 重新显示。 有什么创造性的方法可以做到这一点吗?
迈克尔
发布于 04:30, 4 月 28 日好问题,我自己也在寻找一个不错的解决方案——在这一点上,我发现了一些可能的解决方案——最好的一个可能是使用大卫·格罗斯编写的库的部分(非常棒的作业!)并逐个计算文本符号的大小。 应该可以工作,但欢迎任何其他更实际的解决方案。
是否有人知道是否有 Corona 的本机方法可以直接检索所需的信息?