Tutorial: Sizing Text Input Fields

Tutorial: Sizing Text Input Fields

NOTE: New features have been added to Corona SDK Daily Build 2014.2520 that handles the same tasks that this tutorial covers. If you’re using that build or later, you do not need the code presented below, but for those developers using builds earlier than 2014.2520, this tutorial is still useful for purposes of sizing native text input fields.

In a previous tutorial, we illustrated how to add native text inputs into a display.newGroup() or a Composer scene, allowing them to be moved as a unified group. This week, we’ll discuss how to elegantly configure both the font size and overall size of native.newTextField() input fields.

The reason why native text input objects are challenging is because Corona does not automatically scale fonts in any native UI, including native input fields and other native objects such as web views. Instead, these native objects use the system’s default font size, so while the defined content area (and the native objects) may be scaled relative to the actual content area, their font sizes are not. Consider this simple example:

With a content area of 320×480, one pixel would equal one “point” measurement on an older device like the iPhone 3GS. In this case, because we defined the text size of both objects as 20, the myText text object would be 20 pixels (and points) tall and the native input’s text would also be 20 pixels (and points) tall. However, if we tried this same code on an iPhone 4S with its real screen being 640×960 — exactly double the size as the 3GS — Corona would automatically scale the myText text to be 40 pixels tall. The device would scale the text field font and the text field based on it’s point’s system.  iOS would double the size on Retina displays.  Android would scale up depending on its DPI settings.

Implementing Scaling

There are two options to consider when approaching the sizing of text input fields:

  1. Make the text inside the native.newTextField() match the height of display.newText() labels or other related text, while the height of the overall input box remains variable.
  2. Make the height of the native.newTextField() fixed and force its text to fit inside.

There are, of course, considerations regarding both methods. Using fixed-height boxes is easier for layout purposes, but matching other text object sizes may look better. Ultimately, the UI design and layout will dictate which approach is best.

Now, let’s create two utility functions and attach them to the native.* library since they are related to native text input fields. In this way, both functions become part of the native library and you can call them throughout a project.

Making the Field Fit the Text

This first function makes the input field boundaries properly fit around the text. It returns a native.newTextField() along with the scaled font size.

This function first creates a standard text object in the specified size. Once created, Corona gets this text object’s display.contentHeight() and then immediately disposes of it. This is an important step because each device’s OS renders text a bit differently and we need a basis to measure upon. The next step is to calculate the scaled font size and the combined vertical margin for the input field. This considers Corona’s content scaling as well as various device adjustments. For iOS, this means handling iPhone and iPad a little different. For Android, we can adjust using the difference between the device’s real DPI and the 160 points-per-inch visual scale discussed here.

With the calculations complete, a native.newTextField() is created, its .size is set to scaledFontSize, and the object is returned to the caller along with the scaled font size value.

Making the Text Fit the Field

This next function is useful when the input field should be a fixed height and its text must fit within its boundaries. Unlike the above function which creates the text field, we’ll need to create a text field first and pass it to this function.

This function first calculates the text margin, applying both Corona’s content scaling and the device’s DPI-dependent scaling. Next, it creates a temporary text object, measures its height, and computes the unscaled font size based on the height of the text field (minus the margin). Then it calculates the natveScaledFontSize value, applying the device’s scaling. Finally, it returns this size to the caller.

Remember that to use this function, we must first create the text field and then set the field’s font size based on the returned value of the function call:

Gotchas

As always, when dealing with native objects, you should test on as many actual devices as possible. While the Corona Simulator for Mac allows for basic preview of input text fields, the text inside these fields will not be automatically scaled if the Simulator window is zoomed in or out — it will only be displayed at the correct size when the Simulator window is at normal zoom.

Conclusion

Hopefully this tutorial has illustrated some useful tips — and two convenient functions — which can help you better implement native text fields on varying platforms.

Rob Miracle
rob@coronalabs.com

Rob Miracle creates mobile apps for his own enjoyment and the amusement of others. He serves the Corona Community in the forums, on the blog, and at local events.

1Comment
  • Andreas
    Posted at 03:02h, 05 December

    Hi Rob,

    Thanks a lot, this is just what I needed! Will put it into my code immediately.

    Best,
    Andreas