18 November 2014
Tutorial: Moving native text input fields/boxes
One challenge for Corona developers is how to deal with native.newTextField() and native.newTextBox() objects, in particular when they are located in the lower half of the screen where they can be covered by the device’s keyboard. A common solution is to explicitly move native text field/box objects upward by some variable “keyboard height” when the keyboard becomes active, thus keeping them within view/access of the user.
Using display groups
For simplicity, native objects can be moved as one “unit,” specifically as part of a display.newGroup() which may contain supporting objects like a background, images, buttons, etc. Consider this code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
display.setDefault( "background", 0.5 ) -- Create forward references for UI objects local value1, value2, result -- Create new display group for the UI objects local UIGroup = display.newGroup() -- Listener function for text input events local function textListener( event ) if ( event.phase == "began" ) then -- Transition group upward to y=50 transition.to( UIGroup, { time=1000, y=50 } ) elseif ( event.phase == "ended" or event.phase == "submitted" ) then local v1 = tonumber( value1.text ) local v2 = tonumber( value2.text ) if ( v1 and v2 ) then -- Update the "result" text object result.text = v1 + v2 -- Dismiss (hide) the native keyboard native.setKeyboardFocus( nil ) -- Transition group back down to y=300 transition.to( UIGroup, { time = 1000, y = 300 }) end end end local title = display.newText( "Add two numbers", display.contentCenterX, 75, native.systemFont, 40 ) title:setFillColor( 0, 0, 0 ) UIGroup:insert( title ) value1 = native.newTextField( display.contentCenterX, 150, 160, 40 ) UIGroup:insert( value1 ) value1:addEventListener( "userInput", textListener ) value1.inputType = "number" value2 = native.newTextField( display.contentCenterX, 225, 160, 40 ) UIGroup:insert( value2 ) value2:addEventListener( "userInput", textListener ) value2.inputType = "number" local plus = display.newText( "+", display.contentCenterX-120, 215, native.systemFont, 80 ) plus:setFillColor( 0, 0, 0 ) UIGroup:insert( plus ) result = display.newText( "______", display.contentCenterX, 300, native.systemFont, 80 ) result:setFillColor( 0, 0, 0 ) UIGroup:insert( result ) local equals = display.newText( "=", display.contentCenterX-120, 300, native.systemFont, 80 ) equals:setFillColor( 0, 0, 0 ) UIGroup:insert( equals ) -- Initially position the group at y=300 UIGroup.y = 300 |
This code creates a simple UI (User Interface) consisting of two text fields named value1
and value2
, plus (+) and equal (=) text objects, a title text label, and a label to hold the results of summing the two fields. All of these objects are inserted within the UIGroup
display group, including the native text fields. Thus, when we position the group — or transition it upwards or downwards — everything moves in unison.
Of course, this doesn’t mean that you can position native objects in front of normal display objects — native objects will always appear in front of other display objects, but we can still handle the movement and positioning of these objects as one collective group.
Note that when handling the text field inputs, we confirm that a value has been entered into both fields before transitioning the group back down. We also confirm that each value is a number to avoid any potential errors in summing them together. With these two checks in place, the fields will remain accessible above the keyboard while the user interacts with them, and then when both have valid entries, the group can transition back down while the keyboard is simultaneously dismissed/hidden. Of course, depending on your own design, this approach may vary, but you should ensure that the input fields remain accessible for the duration of the required interactivity.
Conclusion
As demonstrated, this method is useful for handling native input objects. It can benefit developers of business/utility apps in particular, since apps in these categories often rely on keyboard-based interaction.
Fernando Faria
Posted at 02:56h, 20 NovemberWhen we will have the option to get the height of the native keyboard?
joseanquiles
Posted at 22:37h, 20 NovemberThank you Rob. It clarifies a lot about native text fields.
I thougth that text fields cannot be inserted in groups.
Only one doubt: how can I discover the y position in order to text field not being hidden by keyboard?
Rob Miracle
Posted at 14:13h, 22 NovemberIf you text field is called “myTextField” then you can get it’s Y position using: myTextField.y.
RuneW
Posted at 00:40h, 21 NovemberI think maybe group support for textFields is one of the news in the new public release?
This makes things a bit easier, but I look forward to the glorious day when Corona manages to make a textField WIDGET instead of relying on the native textField!
Such a widget will be made so that the group in which it was placed, will automatically scroll up to a given position when the widget has focus. It wil work in the Android emulator. And the text inside will actually behave in a predicatable way and not look like the demo above does on my Galaxy S5 phone (with “1” in the first line and “2” in the second line):
http://www.sub20hz.com/fun/android/android_textField.png
I’m looking forward to this day!
ojnab
Posted at 13:10h, 22 NovemberDidn’t now it was possible to insert native textfields to groups. Does this behaviour apply to other native display objects? Also does it mean that textfields inserted in groups will also be destroyed if i call removeSelf on the group?
deniz
Posted at 04:10h, 23 NovemberHow would you place a native text field just above the keyboard? On Android devices keyboard height varies from device to device (or its operating system specific), on ios devices it also varies if you are using some alternate keyboards. That Corona limitation makes it impossible to create a WhatsApp like chat UI. Please implement a function like native.keyboardHeight
Rob Miracle
Posted at 10:56h, 23 NovemberFirst, there is no way to get the the keyboard height for Android. Engineering has been experimenting with automatic panning where the screen will scroll it into view for you. It seems to be working on Android, but it only works on iOS is single orientation apps. Because this is an experimental feature, has some pretty major limitations on iOS, we didn’t cover it in the blog. But if you want to play with it, add this key:
CoronaWindowMovesWhenKeyboardAppears = true,
into the settings->iphone->plist table for iOS or
coronaWindowMovesWhenKeyboardAppears = true,
into the settings->android table for Android in your build.settings. Yes they start with different case letters. The Apple standard is to capitalize the first letter, the Google standard is to lower case it. This will cause the active field, if it’s below the keyboard to pan into view. There are no extra controls to move it anything more than flush with the top of the keyboard.
Due to the complexity to get this working, it may be a while before Engineering gets back to this. You can use it as long as you understand the limitations.