Tutorial: Text Input with Native UI

Posted by

Text Input in Corona TutorialWith the rise in dominance of mobile platforms for personal computing, the ability for developers to create apps that allow users to input text—whether it’s just a single line for a few words or long-form notes—is more important than ever (especially for those creating non-game apps).

Fortunately, Corona SDK makes it easy for developers to take advantage of two truly native text input widgets: Text Fields and Text Boxes.

So today, I’ll be going over the differences between text fields and text boxes, situations where you’d use one over the other, share some tips, and also walk you through the creation of a simple note app that will allow you to write, save, and load a note!

Let’s get started…

Text Fields vs. Text Boxes

There are several small differences between text fields and text boxes, with a few major differences that really set them apart. Here’s an outline of the capabilities of each one:

Text Fields

  • Can support single-line text input only (no scrolling).
  • Can be used as password fields.
  • Can be made to accept only numerical entry (and show the device’s numerical keyboard instead)

Text Boxes

  • Supports multi-line text input (and can be scrolled).
  • Allows the hiding of the background (to show text only).
  • Can be set as read-only.

Once you begin working with the two, the differences become immediately apparent, so don’t worry about trying to memorize everything that each one can/cannot do. If it helps, I like to think of how “boxes” are meant to hold many items, and therefore text “boxes” can support more text (e.g. multi-line) than their text field counterparts.

Here are some things that both objects support:

  • Change font, font size, and font color of inputted/displayed text.
  • Change the background color.
  • Allows listening for “userInput” events via a callback function.

To see the syntax, as well as a complete listing of associated properties and methods, be sure to view the official documentation for native text fields and text boxes:

Events and Listeners

In the previous section, I briefly mentioned how you can listen for “userInput” events via a callback function, so I’ll go ahead and explain that a little more.

When you create a text field or a text box, you can optionally specify a function that will serve as a “userInput” event listener. Whenever an event is detected for that object, the function you specify will be called (standard fare for Corona Events)—this is known as a callback function.

Similar to how touch events work, “userInput” events have several phases you can listen out for, which are accessed via event.phase in your callback function and are listed below:

  • began: This phase corresponds to when the user keyboard appears on-screen. Typical actions during this phase include the shifting of on-screen elements to account for any important elements the keyboard might be covering up.
     
  • editing: This phase is triggered while the user is typing into the field/box, on every edit.
     
  • ended: When the field/box loses focus, for example, if the user taps another input field/box.
     
  • submitted: This phase corresponds to when the user presses return/enter on the keyboard, thus “submitting” the contents of their text input.
     

Here’s an example of what a “userInput” callback listener function might look like:

local function onUserInput( event )
    if event.phase == "began" then
        print( "Keyboard has now shown up." )

    elseif event.phase == "edited" then
        print( "User has entered text." )

    elseif event.phase == "ended" then
        print( "We have lost focus." )

    elseif event.phase == "submitted" then
        print( "User is done editing, let's do something with text." )
    end
end

 

Not Normal Display Objects!

To be clear, native text fields and text boxes are NOT your usual Corona display objects—they are truly native. And while you can modify their x, y, and alpha values as with other Corona display objects, you cannot insert these objects into groups—they will always appear above ALL other Corona display objects. This may seem counter-intuitive, but there are workarounds you can put in place to make it seem as though these objects belong to the rest of your Corona “stage”.

Overall, it depends on the needs of your app, but here are some suggestions as to things you might do to make native elements blend into your app a little better:

  • Use rectangles, rounded rectangles, and text objects to serve as “placeholders” for your native objects. When a user touches the placeholder, display the native object directly above while the user is editing. When the user finishes, update the placeholder to match and remove the native object.
     
  • Do transitions, etc. on your placeholder objects.
     
  • Hide the background of text boxes (with the hasBackground property) and create your own background (using a normal Corona display object) to truly make text boxes blend in with your app.
     

Those are just a few things you can do, but should be enough to give you some ideas as what you can do with your own app.

And one last important note: You can and should remove native objects as you would with other Corona display objects: by using object:removeSelf() and setting the variable to nil.

Simulator Notes

Currently, native text boxes and text fields work on the Mac Simulator, Xcode simulator, and on device. Please note that if testing using the Mac Simulator, you should build for device or Xcode simulator because there are some differences between native widgets on Mac and iOS.

Being able to use/see text fields and text boxes on the Mac simulator helps reduce some development time by allowing you to test your listeners, events, etc. but should not be used to judge final outcome in terms of functionality and/or appearance.

For absolute best results when testing, build for device.

Basic Note App

Coroan Note AppNext, I’ll walk you through the creation of a simple note app that allows you to write a note and save it for later loading. It’ll demonstrate the creation of text fields and text boxes, as well as dynamically populating it with text from an external source (in this case, a text file).

All code that is shown all belongs to a single file, main.lua (each step builds onto the code from the previous step).

1. Creating the Interface

This step is pretty straight-forward, and doesn’t have anything to do with native text fields. What we’ll be doing is creating the app’s background, the titlebar at the top, and two button widgets.

If you can’t see the code below, view it here.

2. Text Box and Text Field

Next, we’ll create the text field and the text box object. Notice how we must use native.newFont() to set the font property for both native text widgets. Another thing to keep in mind is that text boxes are read-only by default, so we must set the isEditable property to true to allow users to edit the contents.

If you can’t see the code below, view it here.

3. Saving and Loading

Next, we’ll create two functions that will handle the saving and loading of new notes. These functions will be called when users press the ‘Save’ and ‘Load’ buttons at the top of the screen. Additionally, the loadSavedNote() function is called when the app initially loads (to auto-load any note that was previously saved).

If you can’t see the code below, view it here.

Full Source Code

And that’s it! Once you have all the three sections above put together (as well as images for the background, load button, and save button), you’ll have a fully functional little note-taking app! Of course, it only supports a single note but with some effort it can definitely be extended to handle more.

Here’s the entire source for all three parts of the main.lua file (if you can’t see it below, view it here):

Alternatively, if you want the entire project to learn from you can download the entire project from GitHub.

Ready to get started?

Create amazing games and apps for iOS & Android

16 Comments

Robert BinghamFebruary 7th, 2012 at 8:19 pm

So if you wanted to take Notes then post directly to a mssql database or mysql database hosted on a domain. Would you use the submit button to call the SQL instance and post to that or would you connect to a local SQLLite db and background post that information after you submit you note or text field. This is a question mainly for non game use. Thank you in advance. Signed nearly N00B

Rodrigo RSCdevFebruary 7th, 2012 at 9:47 pm

Hi Jon,

Thanks so much for this tuto.

PS: Would you mind sharing the “sample code” full? (I mean, with the images?) as it would be easier to run.

Thanks!

Rodrigo RSCdevFebruary 8th, 2012 at 12:23 am

PS: HOW can I set the keyboard to disapear after I input text using the sample above?

Thanks in advance.

Jonathan BeebeFebruary 8th, 2012 at 12:49 am

@Robert Bingham: I believe you should be able to do it both ways, so it’s just a matter of personal preference. Personally, I’d store input into a local variable and work with that instead.

@Rodrigo RSCdev: I just uploaded the NoteSample to GitHub (also updated the article with the link), and here’s the code you use to hide the keyboard:

native.setKeyboardFocus( nil )

More information here:
http://developer.anscamobile.com/reference/index/nativesetkeyboardfocus

Rodrigo RSCdevFebruary 8th, 2012 at 1:01 am

@Jonathan Bebee – THANK YOU VERY MUCH AS ALWAYS! .)

PS: Sorry the CAPS but I want to make you sure how much am pleased about it.

Cheers,
Rodrigo.

SimeFebruary 8th, 2012 at 10:57 pm

I was using these for user account details, but ended up having to split things up in steps as I couldn’t get a nice scroll effect on them. Basically, the fields end up above my nav bar when I scroll, not what I want. I tried using a mask but that didn’t work either. Any good tips on that? Have a bunch of TextFields that you can use in a ScrollView widget?

Rok ArnusFebruary 9th, 2012 at 2:49 am

When is Windows Simulator support comming?

BrianFebruary 10th, 2012 at 12:13 pm

is there a way that i could see make the background for the text box to go away. So it looks like you are writing on the background? Thanks

amirflFebruary 10th, 2012 at 12:18 pm

Is there a good example of how to implement the placeholders?

sunmilsFebruary 12th, 2012 at 2:35 am

The Possibility to hide the background of Textfields would be very useful, too.

Jonathan BeebeFebruary 13th, 2012 at 8:01 pm

@Brian: You can hide the background of text boxes by setting the hasBackground property to false after you create it. Currently, you cannot do the same with textfields.

@amirfl: There is no example at the moment, but the high-level logic would be to create a display object from an image that LOOKS like a textfield, place the current value of .text in it (using display.newText), and then add a touch listener to that object that will overlay a textfield over it when the object is touched. When the user is done editing, you would then remove the real textfield, update the text on top of the placeholder graphic, and it should look very seamless (depending on the grpahic you used, of course).

KyleFebruary 13th, 2012 at 11:53 pm

Jonathan, thanks for the great weekly tutorials. I believe sunmils was referring to build 737′s release notes:

“Also, adds o.placeholder (string) property for textfields.”

Implying a way to set the default text for one of these fields automatically, except that doesn’t seem to work, i.e.:

textField.placeholder = “This is what you see before you type”

KyleFebruary 14th, 2012 at 12:41 am

Oops, guess I should take the “iOS:” label at the front of that bullet point more literally – it works on iOS devices but not in the mac simulator. It’d be great to get this in the docs, it’s a handy addition :)

BradFebruary 14th, 2012 at 9:31 pm

I submitted a bug on this, setReferencePoint on the native.textinput field gives different results on android and iOS

MichaelFebruary 24th, 2012 at 9:58 am

Thanks for the tutorial, Jonathan! As always it’s a big pleasure to read your posts.

I have a specific question. I need to check what the user is typing in the autocomplete function. So, it’s definitely “editing” phase. Everything is works great, but I want to wait a little bit, until the user will slow down or stop typing to not send 5 http-requests in one second.

So I want to include a delay (300-500 ms) during editing phase. If next character has typed in this delay time, timer is reset again, if not – request is sending to a database.

Is it possible and how to do it?

MJBMarch 2nd, 2012 at 5:01 pm

My app got rejected by Amazon because the edit showed with a red line in with only remnants of the top or bottom of the text showing.

Device:Motorola Droid 2.2, samsung galaxy tablet,HTC Evo Issue: The app contains distorted UI. Please follow the steps to reproduce 1.Install and launch the application. 2.Tap on the save File. 3.Enter the file name and observe that the text is not display in text box.

Leave a comment

Your comment