Posted on by

At the basic level, creating and positioning text in Corona SDK is simple: just create the object at the desired position in the specified font size and you’re done. For example:

local myText = display.newText( "Hello World", 200, 200, native.systemFont, 16 )

However, when you need to position/align text in creative ways, things get a bit more complicated. In this tutorial, we’ll inspect the actual display object that Corona generates via display.newText() so that you can understand and achieve advanced positioning and alignment.

The Basics

Under the hood, Corona takes the information that you pass to the display.newText() API and it generates an image, rendered to texture memory like any other display object. Because Corona SDK uses the operating system’s font rendering, fonts may render differently between devices and the Corona Simulator, in particular between Windows and OS X.

Single-Line Method

The most basic usage of display.newText() is the single-line method. Using this method, you simply output a string of text to the screen. Once it’s rendered by Corona, the theoretical “bounding box” (indicated by the green line) will fit precisely around the text display object:

positioningText1

In regards to screen position, the x and y of this “box” is based upon its center point. You can, of course, position any text object via this center point, but if you’re building a series of text objects such as labels on a statistics screen, you’ll probably want to left-align all of them to a vertical “guide line.” This can be accomplished using anchor points, where — in regards to the x position — an anchor point of 0 indicates the left-most point of the object, 0.5 indicates the center x point, and 1 indicates the right-most point. A similar concept applies to the y anchor point, where a y anchor of 0 represents the object’s top, 0.5 the vertical middle, and 1 the object’s bottom.

Let’s inspect a basic example:

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

Because the anchorX value is set to 0 (the left edge), and the x value is set to 10, this code block positions the text with its left edge 10 points to the right of the content area’s vertical 0 point. Remember, however, that you’re not “aligning the text,” but rather positioning its bounding box (this point will become more important further on).

Multi-Line Method

For more advanced alignment, you may utilize the multi-line method. In this case, you pass a table of options to the display.newText() call. Most of these options mimic those from the “shorthand” single-line declaration outlined above, but there are three additional properties which extend the alignment possibilities: width, height, and align.

width

This property specifies the width of the multi-line “bounding box” in pixels. This is similar to drawing a flexible text box in a graphics application like Photoshop or Illustrator, where the text — no matter how much you enter within the box — will wrap within the confines of its boundaries. As expected, if a word is too long to fit within the remaining width available on that line, it will wrap to the next line.

height

If specified, the text will be cropped at this value, in pixels. If you want an “unlimited” height for the text box, set this value to 0 and the box height will adjust depending on the amount of text within it. However, it will never exceed the maximum texture size limit for the device.

align

This specifies the alignment of the text when the width parameter is supplied. Default value is "left". Valid values are "left""center", or "right". We’ll discuss this in more detail shortly.

Principles of Alignment

Although it may seem non-intuitive to create a single line of text using the multi-line method, let’s explore the advantages from Corona’s standpoint:

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 )

Because the string Hello World, in the default system font at size 24, fits within the width of 200 pixels, it won’t wrap to a second line. Thus, this code visually produces a single line of text. However, while it may appear the same as the first example, it’s important to understand that the “bounding box” is now 200 pixels wide, not the pixel width of the actual text that you see on the screen:

positioningTextLeft

In this manner, you can build a series of fixed-width text boxes and position them in a more unified manner rather than dealing with various text object sizes produced via the single-line method.

Want to right-align the text? Simply change the align parameter to "right"

positioningTextRight

Or you may change it to "center"

positioningTextCenter

In addition to these flexible alignment options, another advantage to multi-line method is that it lets you change the value of the .text property and, if the new string is longer or shorter, the box remains at the fixed width and the text won’t shift unexpectedly. In single-line mode, by comparison, if you position a text object by its center point and change the text string, the object may not align as you intended.

Multiple Lines

Of course, multi-line mode supports multiple lines as well! Let’s see how it looks in the three different alignment options:

tpss1

“left”

local myText = [[This is a long, multi-line string where we are randomly
inserting some blank
lines
of text.]]

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 )
tpss2

“center”

local myText = [[This is a long, multi-line string where we are randomly
inserting some blank
lines
of text.]]

local options = {
   text = myText,
   x = display.contentCenterX,
   y = display.contentCenterY,
   width = 200,
   height = 300,
   fontSize = 24,
   align = "center"
}

--Output the text box with the specified options
local textField = display.newText( options )
textField:setFillColor( 0, 0, 0 )

tpss3

“right”

local myText = [[This is a long, multi-line string where we are randomly
inserting some blank
lines
of text.]]

local options = {
   text = myText,
   x = display.contentCenterX,
   y = display.contentCenterY,
   width = 200,
   height = 300,
   fontSize = 24,
   align = "right"
}

--Output the text box with the specified options
local textField = display.newText( options )
textField:setFillColor( 0, 0, 0 )

As you can see, the align option affects the positioning of the text within the box. In all of these examples, the height of the box is defined at 300. If you set the height to 0, the bounding box will match the actual height of the text. However, this may affect vertical alignment depending on the box’s y anchor setting. Also, while a height setting of 0 creates a text box of “unlimited” height, the text that is created will never exceed the device’s texture size limit. This is an important restriction to be aware of if you place a significant amount of text into a single text box.

On the Topic of Multiple Lines…

In Lua, there is some confusion around how to put line breaks into strings. While Lua supports the traditional double quotes ("...") or single quotes ('...'), it also supports multiple lines via the [[...]] declaration. As such, you may use this method or the Unix “Newline” character (\n) within quotes:

longString = [[This is a really
long string
with multiple
line breaks.]]

--OR...
longString = "This is a really\nlong string\nwith multiple\nline breaks."

Note that if you attempt to input multiple lines using Corona’s single-line method, the line breaks will be ignored.

In Summary

Hopefully this tutorial has shown you some useful techniques for aligning text in Corona SDK. With the single-line method and the more powerful multi-line method, almost any alignment scenario should be possible with just a few lines of code.


Posted by . Thanks for reading...

18 Responses to “Tutorial: Methods for Positioning Text”

  1. JCH

    Unfortunately it’s not very easy to change color inside a text (for instance to highlight a search result).
    What about a “htmlText” option that would allow “simple” changes like color or attributes (bold, italic)

    Reply
    • Rob Miracle

      Corona SDK display.newText() isn’t designed for doing rich text. We recommend that you write a small HTML/CSS file out to your temporary directory and show it with a native.newWebview if you need more stylized text. There have been a couple of community projects to support more rich text as display objects. You would have to search the forums for it.

      Reply
  2. Steve

    Of course the thing they wont tell you and isnt covered anywhere is there is a limit to how much text you can put in newText object before it wont show or throw an error. If you run into this problem the trick is to loop multiple smaller blocks into a display object positioning the next text block after the previous

    Reply
  3. Hendrix

    I have used this feature in one of my games with custom fonts recently and it realy works nice on IOS and I tested it on a galaxy 4s too and it rendered nice there too (not shure how this applies to other displays though.
    Nice tut Rob, as allways :)

    Reply
  4. primoz.cerar

    I have played with text quite a bit and I have one question.
    Would it be possible to set values so that the text would cropped at width and not wrapped. I have a situation where I have to crop text at width if it is too long but I don’t want to fiddle with height to make sure only one line is shown also wrapping will go to new line sooner so there might be room at the end for a couple of letters.
    Am I just better off using containers for this?

    Reply
  5. sunmils

    You can also use my Text Wrapper Class for automatic font sizing, so the Text will always fit you given size, independent of its length. You can find it in the new code exchange.

    Reply
  6. Praveen

    Thanks Rob. The multi-line facility is fantastic – especially when it comes to unicode where char sizes vary a lot.
    However, I have one complaint – the text rendering gets cropped to the “height”. This leads to fractions of a line being displayed. This makes for bad visuals.
    It would be really nice to know which char will end up being the last character in the last fully rendered line. Then I can just trim the text to the right length and add a “…” and redisplay using newText(). Any creative way to do this?

    Reply

Leave a Reply

  • (Will Not Be Published)