有些人尝试在 Corona 中创建异常大的文本块,但发现不起作用。这是因为 Corona 的图像核心基于 OpenGL。这意味着屏幕上几乎所有东西都是图片… 甚至是文本。
更具体地说,在 “原生” 应用程序中,文本只是屏幕上的一个对象,但在 OpenGL 中,所有内容都必须渲染为图像纹理。因此,为了让文本出现在屏幕上,Corona 会采用您传递给 display.newText() 的字符串值,并命令的操作系统的字体引擎使用您提供的字体指标生成图片。然后,返回一个 Corona 显示对象(纹理)并在屏幕上渲染。
为什么这可能是大块文本的问题呢?基本上,如果您渲染一段极长的文字(或段落),您可能会超出设备的最大纹理大小限制。在 OpenGL 中,此最大纹理大小定义为呈现图片所能容纳的最大像素限制 —
幸运的是,大多数现代设备支持至少 2048 像素的纹理大小,为了您的方便,Corona 通过以下 system.getInfo() 调用提供此信息
system.getInfo( "maxTextureSize" )
即使考虑到合理的 2048 像素纹理大小限制,在通过
在计算机历史的早期,对于定义计算机所使用的字符集有两项相互竞争的标准:ASCII 和 EBCDIC。最后 ASCII 击败 EBCDIC,现在几乎所有内容(包括 macOS、Windows、Android 和 iOS)都是
ASCII 在一个字节的数据中包含 26 个大写字母、26 个小写字母、数字以及各种符号字符。除了您已知的可见字符外,ASCII 还包括一系列控制字符。事实上,前 31 个字符都是控制字符!这些控制字符可用于控制屏幕上的文本定位,它们的传统可以追溯到古老的手动打字机。其中包括
对于我们这些还记得手动打字机的人来说,回车会使打字头回到页面左侧。它本身不会将纸张推进到下一行,因此如果你在回车后开始打字,你会覆盖前一行。因此,需要第二个称为换行的动作来将纸张推进一行。
计算机尝试模仿此系统,但不同的操作系统对它的处理方法略有不同。Microsoft DOS
当今,Android、macOS 和 iOS 均基于 Unix,因此更通用的标准是使用单个
^J
= \n
^M
= \r
为了澄清,当你看到插入符号 (^
) 时,它表示\
) 时,它表示转义字符,因此在本例中,\r
是返回\n
是换行符
在 Corona 中有两种渲染
一种将文本换行到下一行的方法是在你传递给 display.newText() 调用的字符串中定义换行符。由于我们移动设备的操作系统\n
等转义版本。事实上,你可能见过如下
local myString = "First line of text.\nSecond line of text.\nThird line of text."
以这种方式指定多行将在 Corona 中被视为单独的视觉文本行。
或者,你可以使用 Lua 的
local myString = [[First line of text. Second line of text. Third line of text.]]
请注意,在这种情况下,你无需像第一个版本中那样指定换行符 (\n
) 标记。
现在,如果你将此 myString
变量传递给 display.newText(),你将获得如下所示的文本输出。在你指定 \n
(或在[[ ]]
格式中启动一个新的代码行)的每一点,文本都将换行到下一行。\n\n
。
所有支持文本的现代设计/布局应用程序都允许你创建文本框,无论其
display.newText() 的 width
参数非常方便地支持该概念。通过指定像素宽度,可以指示文本在该点换行,例如
local myString = "The quick brown fox jumped over the lazy dog." local myText = display.newText( myString, 30, 30, 200, 0, native.systemFont, 24 )
其中,display.newText()
命令中 200
的值指示 Corona 创建一个宽为 200 像素的文本框,从而获得此处所示的输出。紧随其后的 0
参数表明文本框为 灵活高度,这意味着呈现的文本对象的宽度将根据提供的文本字符串自动调整。尽管可以为该框设置静态高度,但通常不建议这样做,因为它可能会导致文本内容在框的较低边界点被视觉截断。
如果您正在创建诸如
幸运的是,您可以循环遍历一个较长的文本串,如上所述,将其分解为较小的块,可由 OpenGL 适当地呈现,确保它们不会超过最大纹理大小限制。执行此操作时,一种选择是使用自然语言概念 段落 来拆分长文本块。让我们进一步探究一下...
对于本教程,我们将使用由 www.lipsum.com
生成的文本local myText = [[Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque semper mollis erat a interdum. Praesent tristique diam in nulla varius, nec aliquet mauris posuere. Suspendisse pretium risus lacus, commodo lacinia sapien dictum et. Sed non varius felis. Curabitur elementum tortor non libero pulvinar, at convallis lectus varius. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur sit amet nunc congue, molestie erat vel, facilisis turpis. Morbi vitae diam ligula. Suspendisse purus turpis, commodo in aliquam id, lobortis a sapien. Sed at libero porta, aliquam odio nec, porta dui. In a congue velit. Aliquam ac quam feugiat, ultricies metus nec, porta neque. Phasellus posuere mollis magna, ac vestibulum ligula congue id. Pellentesque imperdiet aliquam lacus, ac pellentesque dui eleifend nec. Suspendisse auctor vehicula facilisis. Pellentesque id massa tincidunt neque luctus varius. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Maecenas sit amet dapibus nulla. Suspendisse ut risus nulla. Maecenas varius elit non faucibus fermentum. Fusce rhoncus, nisl et varius tristique, enim felis egestas purus, et feugiat lorem urna a augue. Maecenas non pulvinar tortor. Aenean condimentum nibh id eros fringilla viverra. Fusce condimentum urna ut volutpat porttitor. Nunc tincidunt congue ligula. Duis placerat felis varius, convallis massa sed, volutpat magna. Sed vitae viverra neque. Integer ac sollicitudin libero, at ornare purus. Aliquam egestas hendrerit tellus. Aliquam eu elit vitae lorem lacinia tempus. Proin vel dictum mi. Maecenas porttitor, justo a dictum volutpat, nisl libero dictum ligula, vitae posuere urna elit a quam. Nam arcu metus, semper suscipit pellentesque ac, tempor ut arcu. Vestibulum eu nibh erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed semper sollicitudin lorem, vel commodo libero commodo eget. Proin lacinia euismod elit vitae porttitor. Proin ipsum neque, dictum at dictum eu, egestas malesuada turpis. Nulla eros lectus, adipiscing eget velit sed, malesuada aliquam ipsum. Curabitur et egestas massa. Vestibulum luctus est est, tincidunt viverra nisi vulputate id. Integer lobortis tellus eu ligula viverra egestas. Quisque commodo, massa vel pretium imperdiet, nisl enim euismod justo, sed ultricies lacus mi ut nisi. Maecenas molestie vitae magna non interdum. In gravida ornare orci in vulputate. Praesent suscipit lobortis dui ut interdum. Proin pulvinar metus ligula, a malesuada nunc interdum at. Aenean et scelerisque enim. Integer eget congue sapien. Etiam suscipit mauris neque, id semper quam volutpat vel. Proin venenatis dictum felis quis ultricies. Suspendisse feugiat mi congue ante gravida, id accumsan leo mollis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In hac habitasse platea dictumst. Nulla facilisi. Nam arcu mauris, convallis sit amet dictum consequat, imperdiet at mi. Vestibulum velit erat, accumsan sit amet vehicula vitae, tempor id nisi. Quisque eu tellus vulputate nisi vestibulum tincidunt at vitae tellus. Quisque sed pretium nisl. Vivamus a aliquet purus. Integer pulvinar neque in dapibus pharetra. Quisque convallis urna vulputate ligula mattis dictum. Vivamus pharetra molestie nunc, ac rhoncus dolor euismod at. Cras fringilla sollicitudin sapien vel sagittis. Donec dignissim scelerisque mi nec pulvinar. Mauris at metus gravida, lacinia dolor quis, vehicula lacus. Donec a pellentesque tellus. Praesent sit amet lorem nisl. Pellentesque interdum felis quis vehicula vestibulum. Donec ut dolor tortor. ]]
现在,让我们添加一些代码来容纳如此大量的文本
local widget = require( "widget" ) local scrollView = widget.newScrollView( { top = 0, left = 0, width = display.contentWidth, height = display.contentHeight, horizontalScrollDisabled = true }) local paragraphs = {} local paragraph local tmpString = myText local yStart = 10 local mainPadding = 20
让我们仔细检查此代码
由于这五段较长的文本显然不能放在屏幕上,因此它们将被插入到 widget.newScrollView() 中。因此,我们必须首先 require()
Widget 库(第 12 行),并创建一个新的滚动视图,该视图占据整个内容区域horizontalScrollDisabled
参数设置为 true
来仅将滚动限制为垂直方向。
在此之后,paragraphs
表将保存每个段落的不同 display.newText()
对象(分隔的文本块)。paragraph
和 tmpString
变量将分别保存当前段落文本和已删除当前段落后的字符串副本。
变量 yStart
将用于将每个段落一个接一个地放置在后面,其值为 10
(像素),以便在每个新段落之前提供一些间距。当然,您可以根据您的视觉演示调整此值。至于 mainPadding
,我们将使用它在每个呈现的文本块周围添加一些水平填充。
为了执行主要工作,我们将使用repeat
-until
repeat
循环比 while
循环更有意义。本质上,此循环将一直运行,直到 tmpString
等于 nil
或 tmpString
的长度为 0
。
repeat paragraph, tmpString = string.match( tmpString, "([^\n]*)\n(.*)" ) paragraphs[#paragraphs+1] = display.newText( { text=paragraph, width=scrollView.width-(mainPadding*2), fontSize=14 } ) paragraphs[#paragraphs].anchorX = 0 paragraphs[#paragraphs].anchorY = 0 paragraphs[#paragraphs].x = mainPadding paragraphs[#paragraphs].y = yStart paragraphs[#paragraphs]:setFillColor( 0 ) scrollView:insert( paragraphs[#paragraphs] ) yStart = yStart + paragraphs[#paragraphs].height until tmpString == nil or string.len( tmpString ) == 0
让我们探讨一下此循环里面发生的情况
首先,我们使用 string.match() 在字符串中搜索 换行 字符(\n
)。此\n
) 为止,任意数量不是 换行 的字符 ([^\n*]
)。这存储在 paragraph
中,然后其余的字符串存储在 tmpString
中。
使用变量 paragraph
容纳一整段文本后,我们通过 display.newText()
创建显示对象,将 paragraph
的值作为 text
参数传入。使用 #paragraphs+1
作为循环索引,它将在 paragraphs
表格末尾创建新的表格条目。在后续行中,我们可以使用 #paragraphs
作为索引来引用新条目。
注意文本对象的 width
参数设置为scrollView.width-(mainPadding*2
——
然后在mainPadding
来提供一些左边空白,并将 y 坐标设置为 yStart
。按照此操作,在
在循环内的最后一行上,我们将 yStart
增加之前创建的段落的高度。这样,你便可以将下一块文本立即定位在前一块文本之下,形成一种错觉,即这只是带有一小段空白的文本长块。
最后,让我们增加滚动视图的总可滚动高度,以便在最后一段下方提供一些垂直填充
scrollView:setScrollHeight( scrollView:getView().height + (mainPadding*2) )
就是这样!有了这段完整代码,你可以构建包含无限段落且在视觉上通过可调节像素量分隔并具备可针对不同字体和字号进行自动换行的滚动视图。
希望本教程已经向你展示了如何通过一点额外的努力来克服纹理大小的限制,进而构建 Corona 中的文本长块。