How to Create a Custom QWERTY Keyboard
Introduction
A QWERTY keyboard UI refers to a keyboard layout that is similar to the standard keyboard layout found on most mobile phones and computers. The name "QWERTY" comes from the first six letters in the top row of the keyboard. This layout includes alpha-numeric and special characters, as well as keys for backspace, enter, arrows, space, escape, and shift.
This how-to guide shows how to use keypad widgets and buttons to create a custom English QWERTY keyboard of a specific key layout. The same concept can be applied to create QWERTY keyboards of any layout.
MGS Example Project
Refer to the project in GitHub for the example.
MGS Simulator Output
This is how the application runs:
- Selecting the Text Field widgets for the Last Name or Confirmation Number will pop up an English QWERTY keyboard.
- Press the keys to enter the Last Name and Confirmation Number.
- When done, press the Enter (→) key to hide the keyboard.
- Press Continue to check the Last Name and Confirmation Number.
- If the right Last Name ("mchp") and Confirmation Number ("1234") are entered, the welcome pop up screen will be shown.
- If not, an error pop up will be shown.
MGS Harmony Composer Design
Here is what the screen design looks like in MGS Harmony Composer. The On Show, On Hide, On Update event callbacks are enabled for this screen. These screen callbacks will be used to initialize and update the screen at run-time.
The visible screen area contains the two text field widgets for the Last Name and Confirmation Number entries and the Continue button.
Selecting these Text Field widgets will show their properties in the Object Editor window. Observe the properties of these Text Field widgets:
- A Hint String was set to show information about the text field.
- The Font was set to the desired font used to show the input string in the text field. Make sure that the font contains the glyphs for the characters in the QWERTY keyboard.
- The Focus Changed event callback is enabled. This will be used in the application to show the QWERTY keyboard when the text field is selected or touched (in focus).
Off-screen on the left are the two pop-up dialog boxes used to show if the entries are valid or not.
Off-screen on the bottom is a parent panel that contains multiple widgets used to create the QWERTY keyboard.
Multiple Keypad widgets were used to create the edit keys, the keys that append, delete, or edit the entry in the Last Name and Confirmation Number text fields.
Selecting each of these Keypad widgets and clicking the Configure property will show how they are configured.
Here's the configuration for the first row keypad.
Two sets of images are set for the Pressed Icon and Released Icon properties to show different pressed and released states of the keys. The Image Position is set to Behind to show the String on top.
For the character keys, the String and Edit Value properties are set to a string asset in the String Manager.
The String Manager was used to create the unique string assets that correspond to the character for that key, including for the normal, shift, and numbers/symbols modes of the keyboard. For example, the q key uses a strq string asset in the String Manager that has a "q" value.
Other non-character edit keys (like Backspace) are set to the corresponding Edit Action.
For the non-edit keys, like shift, enter, and symbols, regular button widgets were used.
The Pressed event callback was enabled for each of these buttons. The callback functions are defined in the application source code.
Application Code
The application code that manages the screen behavior and the callback functions for handling the screen and widget events are defined in the app_ConfirmScreen.c file.
Screen State Machine
The screen state machine is managed in the screen update event callback function, LastNameConfScreen_OnUpdate.
In the running state (CONF_RUN), the function checks if any of the non-edit buttons were pressed. This includes:
- Checking if the shift or number/symbol (?123) buttons are pressed to change the key mapping,
- Checking if the enter button is pressed to switch the edit focus, and
- Checking if the continue button is pressed to transition to the RESULT screen state.
In the RESULT state, the function validates the user-supplied Last Name and Confirmation Number and shows the dialog box to confirm if they are valid or not.
Button Widget Event Callbacks
Button widget pressed or released events are handled using the event handler functions defined in the application code. These handler functions simply set the corresponding application screen event, which are then checked in the screen state machine.
Here's an example callback function that handles the pressed event for the Continue button.
void event_LastNameConfScreen_btnContinue_OnReleased(leButtonWidget* btn)
{
ConfScreen_SetEvent(CONF_EVT_KEYBRD_CONTINUE);
}
Key Character Mapping
To enable the keypad widgets to switch to different keys when the shift or number/symbol (?123) keys are pressed, arrays of structures are used to provide the string asset mapping for each keyboard mode, for each Keypad widget. For example, keyPadRow1 contains the mapping for the first-row keypad.
KEY_CONFIG_t keyPadRow1[NUM_KEYS_ROW1] =
{
{&string_strQ, &string_strq, &string_str1}, /* row 1, key 1 */
{&string_strW, &string_strw, &string_str2}, /* row 1, key 2 */
{&string_strE, &string_stre, &string_str3}, /* row 1, key 3 */
{&string_strR, &string_strr, &string_str4}, /* row 1, key 4 */
{&string_strT, &string_strt, &string_str5}, /* row 1, key 5 */
{&string_strY, &string_stry, &string_str6}, /* row 1, key 6 */
{&string_strU, &string_stru, &string_str7}, /* row 1, key 7 */
{&string_strI, &string_stri, &string_str8}, /* row 1, key 8 */
{&string_strO, &string_stro, &string_str9}, /* row 1, key 9 */
{&string_strP, &string_strp, &string_str0}, /* row 1, key 10 */
};
Each of these string assets was added using the String Manager.
The remapping is done inside the ConfScreen_SetKeyboardConfig function, where each key (cell) in each Keypad widget is assigned the appropriate String and Key Value depending on the keyboard mode (shift, normal, or numbers/symbols).
Here's a code snippet that shows how each cell in the keypad is referenced and configured.
for (i = 0; i < NUM_KEYS_ROW1; i++)
{
/* get the cell/key at specific index */
leButtonWidget * cell = LastNameConfScreen_keysRow1->fn->getCellButton(LastNameConfScreen_keysRow1, 0, i);
/* set the string for the cell/key (what's shown on the GUI) */
cell->fn->setString(cell, (leString *) keyPadRow1[i].text[conf]);
/* sets the edit string for the key/cell (what's appended to text field */
LastNameConfScreen_keysRow1->fn->setKeyValue(LastNameConfScreen_keysRow1, 0, i, (leString *) keyPadRow1[i].text[conf]);
}
Hiding/Showing the Keyboard
The keyboard is contained inside the parent panel widget, pnlKeyboard. By default, the keyboard is hidden by positioning the panel off-screen.
To show the keyboard when the text field widgets are clicked, the OnFocusChanged event callback for the text field widgets was defined so that they reposition the panel widget to show the keyboard in the screen.
void event_LastNameConfScreen_txtFieldLastName_OnFocusChanged(leTextFieldWidget* btn, leBool state)
{
/* if text field widget is selected, show the keyboard panel */
if (state == LE_TRUE)
{
/* Show the keyboard by setting position in frame */
LastNameConfScreen_pnlKeyboard->fn->setY(LastNameConfScreen_pnlKeyboard, 440);
}
}
To hide the keyboard, it's repositioned off-screen when the ENTER button key is pressed.
Updating the Text Field widget
A Keypad widget will automatically target the Text Field widget has gained focus. So when a Text Field widget is touched or clicked, any edit action from a Keypad widget will be directed to that text field.
To direct edit action to a specific Text Field widget, the setFocus widget API is used. For example, when the user presses the Enter button while updating the Last Name Text Field widget, the setFocus API is called to direct the next edit action to the Confirmation Number Edit Field widget. Here's how it is implemented in the application code.
case CONF_EVT_KEYBRD_ENTER:
{
/* If lastname textfield widget is being edited, switch to confirmation number textfield widget */
if (leGetEditWidget() == (leEditWidget*) LastNameConfScreen_txtFieldLastName)
{
LastNameConfScreen_txtFieldConfNum->fn->setFocus(LastNameConfScreen_txtFieldConfNum);
}