The keyboard is an important factor in the mobile application. To keep the application feel native, keyboard should act like in a native way for both platforms.
iOS - iPadOS | Android |
Has one standart keyboard. | Different keyboards can be used. |
Keyboard has theme support, keyboard theme can be changed by application. | Keyboard theming is keyboard-app dependant. Applications can't change keyboard theme. |
Has less types supported. | Has more variety of types. |
Auto-correction, auto capitalisation etc. is handled by Platform and cannot be configured via app. | Auto-correction, auto capitalisation etc. can be configured via app. |
Numeric Keyboard doesn't have action button on bottom corner. | Numeric Keyboard has action button on bottom corner. |
Custom layouts can be added on top of keyboard. | Custom layouts cannot be added on top of keyboard. |
Keyboard will take same space on every device. | Keyboard size is configurable, can be changed per device and keyboard app. |
Only tablets can have floating keyboard. | Both tablets and Smartphones can have floating keyboard. |
Text appearance will not be changed via writing with a keyboard. | Texts might be underlined when typing. It indicates that the text can be changed by auto-correct. |
API Reference: http://ref.smartface.io/#!/api/UI.KeyboardType​
To customize your keyboard experience,
import KeyboardType from 'sf-core/ui/keyboardtype';// TextBoxthis.tbLogin.keyboardType = KeyboardType.NUMBER;// MaterialTextBoxthis.mtbLogin.options = {hint: "Smartface"}this.mtbLogin.materialTextBox.keyboardType = KeyboardType.NUMBER;
On Android, you can have more predefined types. To check them out, refer here.
Keep in mind that on Number keyboard, iOS doesn't have ActionButton within the keyboard. Head over to KeyboardLayout section of this document to handle navigation better.
API Reference: http://ref.smartface.io/#!/api/UI.KeyboardAppearance​
You can change the theme of your keyboard programmatically on iOS.
import KeyboardAppearance from 'sf-core/ui/keyboardappearance';// TextBoxthis.tbLogin.ios.keyboardAppearance = KeyboardAppearance.DARK;// MaterialTextBoxthis.mtbLogin.materialTextBox.ios.keyboardAppearance = KeyboardAppearance.DARK;// Alternativelythis.mtbLogin.options = {hint: "Smartface",ios: {keyboardAppearance: KeyboardAppearance.DARK}}
This feature is iOS only. On Android, keyboard theme cannot be controlled by the application.
For Android, textbox navigation is usually handled by platform. However, if it fails, you can manually set your navigation by using onActionButtonPress method.
For iOS, you can add a custom flexLayout on top of the keyboard, to ease the input navigation.
API Reference: http://ref.smartface.io/#!/api/UI.TextBox-property-keyboardLayout​
Utility Location: https://github.com/smartface/sf-component-keyboardlayout​
To ease out the navigation in multiple textboxes, on iOS there is an utility called KeyboardLayout. It is included in the Smartface project by default.
scripts/pages/page1.tsimport Page1Design from 'generated/pages/page1';import componentContextPatch from '@smartface/contx/lib/smartface/componentContextPatch';import PageTitleLayout from 'components/PageTitleLayout';import System from 'sf-core/device/system';import KeyboardAppearance from 'sf-core/ui/keyboardappearance';import KeyboardType from 'sf-core/ui/keyboardtype';import KeyboardLayout from 'keyboardlayout';​export default class Page1 extends Page1Design {router: any;constructor() {super();// Overrides super.onShow methodthis.onShow = onShow.bind(this, this.onShow.bind(this));// Overrides super.onLoad methodthis.onLoad = onLoad.bind(this, this.onLoad.bind(this));}initMaterialTextBoxes() {const userNameType = System.OS === 'Android' ? KeyboardType.Android.TEXTPERSONNAME : KeyboardType.DEFAULT;this.mtbUsername.options = {hint: 'Username'};this.mtbUsername.materialTextBox.keyboardType = userNameType;this.mtbEmail.options = {hint: 'Email Address'};this.mtbEmail.materialTextBox.keyboardType = KeyboardType.EMAILADDRESS;this.mtbPin.options = {hint: 'Pin Code'};this.mtbPin.materialTextBox.keyboardType = KeyboardType.NUMBER;const keyboardLayouts = KeyboardLayout.init([this.mtbUsername.materialTextBox, this.mtbEmail.materialTextBox, this.mtbPin.materialTextBox]);}}​/*** @event onShow* This event is called when a page appears on the screen (everytime).* @param {function} superOnShow super onShow function* @param {Object} parameters passed from Router.go function*/function onShow(superOnShow: () => void) {superOnShow();}​/*** @event onLoad* This event is called once when page is created.* @param {function} superOnLoad super onLoad function*/function onLoad(superOnLoad: () => void) {superOnLoad();this.initMaterialTextBoxes();}​
.ui/page1.pgx{"components": [{"className": ".sf-page","id": "e891b86d","initialized": true,"props": {"children": ["42b807d1","b7d28cff","ee71-c9bc-30b5-6202","6b34-f2f3-19c9-85e7","442d-5bea-4baf-4959"],"isRemovable": true,"name": "page1","orientation": "PORTRAIT","parent": null,"safeAreaEnabled": true},"type": "Page","userProps": {"flexProps": {"justifyContent": "FLEX_START","alignItems": "STRETCH"},"orientation": "PORTRAIT","paddingBottom": 20,"paddingLeft": 16,"paddingRight": 16,"safeAreaEnabled": true},"version": "6.15.1"},{"className": ".sf-statusBar","id": "42b807d1","props": {"children": [],"isRemovable": false,"name": "statusBar","parent": "e891b86d"},"type": "StatusBar","userProps": {"visible": true}},{"className": ".sf-headerBar","id": "b7d28cff","props": {"children": [],"isRemovable": false,"name": "headerBar","parent": "e891b86d","title": "Page1"},"type": "HeaderBar","userProps": {"title": "Page1","visible": true}},{"className": ".flexLayout .materialTextBox-wrapper","hiddenComponent": false,"id": "ee71-c9bc-30b5-6202","initialized": false,"props": {"children": [],"name": "mtbUsername","parent": "e891b86d","usePageVariable": true},"source": {"page": "__library__","type": "materialTextBox","id": "574a-10da-b765-48e5"},"type": "FlexLayout","userProps": {"flex": {"positionType": 0},"flexProps": {"positionType": "RELATIVE"},"left": 0,"testId": "CVEVkbtyf","top": 0,"usePageVariable": true}},{"className": ".flexLayout .materialTextBox-wrapper","hiddenComponent": false,"id": "6b34-f2f3-19c9-85e7","initialized": false,"props": {"children": [],"name": "mtbEmail","parent": "e891b86d","usePageVariable": true},"source": {"page": "__library__","type": "materialTextBox","id": "574a-10da-b765-48e5"},"type": "FlexLayout","userProps": {"flex": {"positionType": 0},"flexProps": {"positionType": "RELATIVE"},"left": 0,"testId": "X-wG8LqxK","top": 0,"usePageVariable": true}},{"className": ".flexLayout .materialTextBox-wrapper","hiddenComponent": false,"id": "442d-5bea-4baf-4959","initialized": false,"props": {"children": [],"name": "mtbPin","parent": "e891b86d","usePageVariable": true},"source": {"page": "__library__","type": "materialTextBox","id": "574a-10da-b765-48e5"},"type": "FlexLayout","userProps": {"flex": {"positionType": 0},"flexProps": {"positionType": "RELATIVE"},"left": 0,"testId": "NBR4Oxoep","top": 0,"usePageVariable": true}}]}
By default, KeyboardLayout will have:
Down button to navigate to one textbox below
Up button to navigate to one textbox above
Done button to close the keyboard
You can change those behavior by using keyboardLayouts array. The layout object will be returned ordered like it was passed on init method.
You can combine this feature with inputView on iOS to have picker and done button above it.
KeyboardLayout style files will be located in themes/baseTheme/styles/KeyboardLayout.json
by default. You should copy this file and paste into your theme folders. If you have dark theme support, you should also paste the file and edit the values accordingly in both folder. More info is located at: