From 2f6c9d8526cbec714acc5ca06a5ab59be8eb89ba Mon Sep 17 00:00:00 2001 From: Prince Yadav <66916296+prince-0408@users.noreply.github.com> Date: Tue, 1 Sep 2026 02:21:32 +0530 Subject: [PATCH 1/2] refactor: extract KeyboardLayoutHandler from GeneralKeyboardIME (Part 15) - #426 --- CHANGELOG.md | 2 + .../be/scri/helpers/KeyboardLayoutHandler.kt | 129 ++++++++++++++++++ .../be/scri/services/GeneralKeyboardIME.kt | 96 +++---------- .../scri/helpers/KeyboardLayoutHandlerTest.kt | 94 +++++++++++++ 4 files changed, 244 insertions(+), 77 deletions(-) create mode 100644 app/src/keyboards/java/be/scri/helpers/KeyboardLayoutHandler.kt create mode 100644 app/src/testKeyboards/kotlin/be/scri/helpers/KeyboardLayoutHandlerTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 11a8ee45a..68f6f3841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -94,4 +94,6 @@ Emojis for the following are chosen based on [gitmoji](https://gitmoji.dev/). ### ♻️ Code Refactoring - Code quality improvements were continuously done to assure that the application is easy to maintain and meets Kotlin standards ([#426](https://github.com/scribe-org/Scribe-Android/issues/426)). +- `KeyboardLayoutHandler` was extracted from `GeneralKeyboardIME` to encapsulate layout XML resolution, symbol keyboard mapping, and width calculations ([#426](https://github.com/scribe-org/Scribe-Android/issues/426)). - Introduced `KeyboardIMEContext` interface contract to decouple handler dependencies from the concrete `GeneralKeyboardIME` class ([#426](https://github.com/scribe-org/Scribe-Android/issues/426)). + diff --git a/app/src/keyboards/java/be/scri/helpers/KeyboardLayoutHandler.kt b/app/src/keyboards/java/be/scri/helpers/KeyboardLayoutHandler.kt new file mode 100644 index 000000000..738e2a0a3 --- /dev/null +++ b/app/src/keyboards/java/be/scri/helpers/KeyboardLayoutHandler.kt @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package be.scri.helpers + +import android.text.InputType.TYPE_CLASS_DATETIME +import android.text.InputType.TYPE_CLASS_NUMBER +import android.text.InputType.TYPE_CLASS_PHONE +import android.text.InputType.TYPE_MASK_CLASS +import be.scri.R +import be.scri.models.ScribeState +import be.scri.services.GeneralKeyboardIME + +private const val DATA_SIZE_2 = 2 +private const val DATA_CONSTANT_3 = 3 + +/** + * Encapsulates keyboard XML layout resolution, symbol layout mapping, + * keyboard width calculations, state-based layout XML selection, and view re-creation. + */ +class KeyboardLayoutHandler( + private val ime: GeneralKeyboardIME, +) { + /** + * Resolves the XML resource ID for the active keyboard layout. + * + * @return The XML layout resource ID. + */ + fun getCurrentKeyboardLayoutXML(): Int = + when (ime.keyboardMode) { + ime.keyboardSymbols -> getPrimarySymbolKeyboardLayoutXML() + ime.keyboardSymbolShift -> R.xml.keys_symbols_shift + else -> ime.getKeyboardLayoutXML() + } + + /** + * Resolves the primary symbol or numeric layout XML resource ID. + * + * @return The XML layout resource ID. + */ + fun getPrimarySymbolKeyboardLayoutXML(): Int = + if (ime.isNumericKeyboardActive) { + R.xml.keys_numeric + } else { + R.xml.keys_symbols + } + + /** + * Determines which keyboard layout XML to use based on the current [ScribeState]. + * + * @param state The current state of the Scribe keyboard. + * @param isSubsequentArea true if this is for a secondary conjugation view. + * @param dataSize The number of items to display, used to select an appropriate layout. + * @return The resource ID of the keyboard layout XML. + */ + fun getKeyboardLayoutForState( + state: ScribeState, + isSubsequentArea: Boolean = false, + dataSize: Int = 0, + ): Int = + when (state) { + ScribeState.SELECT_VERB_CONJUNCTION -> { + ime.saveConjugateModeType(ime.language) + if (!isSubsequentArea && dataSize == 0) { + ime.defaultConjugateLayoutXML + } else { + when (dataSize) { + DATA_SIZE_2 -> R.xml.conjugate_view_2x1 + DATA_CONSTANT_3 -> R.xml.conjugate_view_1x3 + else -> R.xml.conjugate_view_2x2 + } + } + } + + else -> { + ime.getKeyboardLayoutXML() + } + } + + /** + * Calculates the width of the keyboard container. + * + * @return The keyboard width in pixels. + */ + fun getKeyboardWidth(): Int = + if (ime.isFloatingMode) { + val density = ime.resources.displayMetrics.density + val screenWidth = ime.resources.displayMetrics.widthPixels + val floatWidth = (320f * density).toInt() + Math.min(floatWidth, (screenWidth * 0.85f).toInt()) + } else { + ime.resources.displayMetrics.widthPixels + } + + /** + * Re-instantiates the [KeyboardBase] and applies the updated shift state and layout. + */ + fun recreateKeyboard() { + if (!ime.isUiManagerInitialized) return + + val xmlId = getCurrentKeyboardLayoutXML() + val currentShiftState = ime.keyboard?.mShiftState ?: SHIFT_OFF + ime.keyboard = KeyboardBase(ime, xmlId, ime.enterKeyType, getKeyboardWidth()) + ime.keyboard?.setShifted(currentShiftState) + ime.keyboardView?.setKeyboard(ime.keyboard!!) + + if (xmlId == R.xml.keys_symbols) { + ime.uiManager.setupCurrencySymbol(ime.language) + } + ime.keyboardView?.invalidateAllKeys() + } + + companion object { + internal fun shouldUseNumericKeyboard(inputType: Int): Boolean = + when (inputType and TYPE_MASK_CLASS) { + TYPE_CLASS_NUMBER, TYPE_CLASS_DATETIME, TYPE_CLASS_PHONE -> true + else -> false + } + + internal fun getKeyboardLayoutXMLForInputType( + inputType: Int, + letterKeyboardLayoutXML: Int, + ): Int = + if (shouldUseNumericKeyboard(inputType)) { + R.xml.keys_numeric + } else { + letterKeyboardLayoutXML + } + } +} diff --git a/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt index 9d2d8b5c1..bd4f45a02 100644 --- a/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt @@ -10,9 +10,6 @@ import android.content.res.Resources import android.graphics.Rect import android.inputmethodservice.InputMethodService import android.text.InputType -import android.text.InputType.TYPE_CLASS_DATETIME -import android.text.InputType.TYPE_CLASS_NUMBER -import android.text.InputType.TYPE_CLASS_PHONE import android.text.InputType.TYPE_MASK_CLASS import android.view.KeyEvent import android.view.View @@ -40,6 +37,7 @@ import be.scri.helpers.KeyboardBase import be.scri.helpers.KeyboardDataHandler import be.scri.helpers.KeyboardIMEContext import be.scri.helpers.KeyboardLanguageMappingConstants +import be.scri.helpers.KeyboardLayoutHandler import be.scri.helpers.KeyboardStateManager import be.scri.helpers.LanguageMappingConstants.getLanguageAlias import be.scri.helpers.NativeSuggestionEngine @@ -167,6 +165,7 @@ abstract class GeneralKeyboardIME( override lateinit var autocompletionHandler: AutocompletionHandler internal lateinit var keyHandler: KeyHandler internal val floatingKeyboardHandler by lazy { FloatingKeyboardHandler(this) } + internal val layoutHandler by lazy { KeyboardLayoutHandler(this) } internal var dataContract: DataContract? get() = dataHandler.dataContract @@ -232,7 +231,7 @@ abstract class GeneralKeyboardIME( override var wordSuggestions: List? = null override var checkIfPluralWord: Boolean = false private var currentEnterKeyType: Int? = null - private var isNumericKeyboardActive: Boolean = false + internal var isNumericKeyboardActive: Boolean = false internal val stateManager = KeyboardStateManager() internal val themeManager = KeyboardThemeManager() @@ -281,21 +280,12 @@ abstract class GeneralKeyboardIME( const val COMMIT_TEXT_CURSOR_POSITION = 1 internal const val CUSTOM_CURSOR = "│" // special tall cursor character - internal fun shouldUseNumericKeyboard(inputType: Int): Boolean = - when (inputType and TYPE_MASK_CLASS) { - TYPE_CLASS_NUMBER, TYPE_CLASS_DATETIME, TYPE_CLASS_PHONE -> true - else -> false - } + internal fun shouldUseNumericKeyboard(inputType: Int): Boolean = KeyboardLayoutHandler.shouldUseNumericKeyboard(inputType) internal fun getKeyboardLayoutXMLForInputType( inputType: Int, letterKeyboardLayoutXML: Int, - ): Int = - if (shouldUseNumericKeyboard(inputType)) { - R.xml.keys_numeric - } else { - letterKeyboardLayoutXML - } + ): Int = KeyboardLayoutHandler.getKeyboardLayoutXMLForInputType(inputType, letterKeyboardLayoutXML) } // MARK: Lifecycle Methods @@ -784,19 +774,17 @@ abstract class GeneralKeyboardIME( override fun isNumericKeyboardActive(): Boolean = isNumericKeyboardActive - override fun getCurrentKeyboardLayoutXML(): Int = - when (keyboardMode) { - keyboardSymbols -> getPrimarySymbolKeyboardLayoutXML() - keyboardSymbolShift -> R.xml.keys_symbols_shift - else -> getKeyboardLayoutXML() - } + /** + * Resolves the XML resource ID for the active keyboard layout. + * Delegated to [KeyboardLayoutHandler]. + */ + override fun getCurrentKeyboardLayoutXML(): Int = layoutHandler.getCurrentKeyboardLayoutXML() - private fun getPrimarySymbolKeyboardLayoutXML(): Int = - if (isNumericKeyboardActive) { - R.xml.keys_numeric - } else { - R.xml.keys_symbols - } + /** + * Resolves the primary symbol or numeric layout XML resource ID. + * Delegated to [KeyboardLayoutHandler]. + */ + internal fun getPrimarySymbolKeyboardLayoutXML(): Int = layoutHandler.getPrimarySymbolKeyboardLayoutXML() override fun onKeyboardActionListener(): KeyboardView.OnKeyboardActionListener = this @@ -1969,29 +1957,11 @@ abstract class GeneralKeyboardIME( * * @return The resource ID of the keyboard layout XML. */ - private fun getKeyboardLayoutForState( + internal fun getKeyboardLayoutForState( state: ScribeState, isSubsequentArea: Boolean = false, dataSize: Int = 0, - ): Int = - when (state) { - ScribeState.SELECT_VERB_CONJUNCTION -> { - saveConjugateModeType(language) - if (!isSubsequentArea && dataSize == 0) { - defaultConjugateLayoutXML - } else { - when (dataSize) { - DATA_SIZE_2 -> R.xml.conjugate_view_2x1 - DATA_CONSTANT_3 -> R.xml.conjugate_view_1x3 - else -> R.xml.conjugate_view_2x2 - } - } - } - - else -> { - getKeyboardLayoutXML() - } - } + ): Int = layoutHandler.getKeyboardLayoutForState(state, isSubsequentArea, dataSize) /** * Updates the visibility of the suggestion buttons based on device type (phone/tablet) @@ -2010,29 +1980,10 @@ abstract class GeneralKeyboardIME( // MARK: Floating Keyboard Integration - override fun getKeyboardWidth(): Int = - if (isFloatingMode) { - val density = resources.displayMetrics.density - val screenWidth = resources.displayMetrics.widthPixels - val floatWidth = (320f * density).toInt() - Math.min(floatWidth, (screenWidth * 0.85f).toInt()) - } else { - resources.displayMetrics.widthPixels - } + override fun getKeyboardWidth(): Int = layoutHandler.getKeyboardWidth() - override fun recreateKeyboard() { - if (!this::uiManager.isInitialized) return - val xmlId = getCurrentKeyboardLayoutXML() - val currentShiftState = keyboard?.mShiftState ?: SHIFT_OFF - keyboard = KeyboardBase(this, xmlId, enterKeyType, getKeyboardWidth()) - keyboard?.setShifted(currentShiftState) - keyboardView?.setKeyboard(keyboard!!) + override fun recreateKeyboard() = layoutHandler.recreateKeyboard() - if (xmlId == R.xml.keys_symbols) { - uiManager.setupCurrencySymbol(language) - } - keyboardView?.invalidateAllKeys() - } val isFloatingMode: Boolean get() = floatingKeyboardHandler.isFloatingMode @@ -2077,12 +2028,3 @@ abstract class GeneralKeyboardIME( clipboardHandler.closeClipboardPanel() } } - -private fun Float.coerceInSafe( - bound1: Float, - bound2: Float, -): Float { - val minVal = if (bound1 < bound2) bound1 else bound2 - val maxVal = if (bound1 > bound2) bound1 else bound2 - return this.coerceIn(minVal, maxVal) -} diff --git a/app/src/testKeyboards/kotlin/be/scri/helpers/KeyboardLayoutHandlerTest.kt b/app/src/testKeyboards/kotlin/be/scri/helpers/KeyboardLayoutHandlerTest.kt new file mode 100644 index 000000000..d8986f188 --- /dev/null +++ b/app/src/testKeyboards/kotlin/be/scri/helpers/KeyboardLayoutHandlerTest.kt @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +package be.scri.helpers + +import android.text.InputType.TYPE_CLASS_NUMBER +import android.text.InputType.TYPE_CLASS_TEXT +import be.scri.R +import be.scri.models.ScribeState +import be.scri.services.GeneralKeyboardIME +import io.mockk.every +import io.mockk.mockk +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test + +class KeyboardLayoutHandlerTest { + private lateinit var mockIme: GeneralKeyboardIME + private lateinit var layoutHandler: KeyboardLayoutHandler + + @Before + fun setUp() { + mockIme = mockk(relaxed = true) + layoutHandler = KeyboardLayoutHandler(mockIme) + } + + @Test + fun testGetPrimarySymbolKeyboardLayoutXML_numericActive() { + every { mockIme.isNumericKeyboardActive } returns true + val xmlResId = layoutHandler.getPrimarySymbolKeyboardLayoutXML() + assertEquals(R.xml.keys_numeric, xmlResId) + } + + @Test + fun testGetPrimarySymbolKeyboardLayoutXML_symbolsActive() { + every { mockIme.isNumericKeyboardActive } returns false + val xmlResId = layoutHandler.getPrimarySymbolKeyboardLayoutXML() + assertEquals(R.xml.keys_symbols, xmlResId) + } + + @Test + fun testGetCurrentKeyboardLayoutXML_letterMode() { + every { mockIme.keyboardMode } returns 0 + every { mockIme.keyboardSymbols } returns 1 + every { mockIme.keyboardSymbolShift } returns 2 + every { mockIme.getKeyboardLayoutXML() } returns R.xml.keys_symbols + + val xmlResId = layoutHandler.getCurrentKeyboardLayoutXML() + assertEquals(R.xml.keys_symbols, xmlResId) + } + + @Test + fun testGetCurrentKeyboardLayoutXML_symbolShiftMode() { + every { mockIme.keyboardMode } returns 2 + every { mockIme.keyboardSymbols } returns 1 + every { mockIme.keyboardSymbolShift } returns 2 + + val xmlResId = layoutHandler.getCurrentKeyboardLayoutXML() + assertEquals(R.xml.keys_symbols_shift, xmlResId) + } + + @Test + fun testGetKeyboardLayoutForState_verbConjunction_dataSize2() { + every { mockIme.saveConjugateModeType(any()) } returns Unit + val xmlResId = layoutHandler.getKeyboardLayoutForState(ScribeState.SELECT_VERB_CONJUNCTION, isSubsequentArea = true, dataSize = 2) + assertEquals(R.xml.conjugate_view_2x1, xmlResId) + } + + @Test + fun testGetKeyboardLayoutForState_defaultState() { + every { mockIme.getKeyboardLayoutXML() } returns R.xml.keys_symbols + val xmlResId = layoutHandler.getKeyboardLayoutForState(ScribeState.IDLE) + assertEquals(R.xml.keys_symbols, xmlResId) + } + + @Test + fun testShouldUseNumericKeyboard() { + assertTrue(KeyboardLayoutHandler.shouldUseNumericKeyboard(TYPE_CLASS_NUMBER)) + assertFalse(KeyboardLayoutHandler.shouldUseNumericKeyboard(TYPE_CLASS_TEXT)) + } + + @Test + fun testGetKeyboardLayoutXMLForInputType() { + assertEquals( + R.xml.keys_numeric, + KeyboardLayoutHandler.getKeyboardLayoutXMLForInputType(TYPE_CLASS_NUMBER, R.xml.keys_symbols), + ) + assertEquals( + R.xml.keys_symbols, + KeyboardLayoutHandler.getKeyboardLayoutXMLForInputType(TYPE_CLASS_TEXT, R.xml.keys_symbols), + ) + } +} From 2ab5b6a39b29e928cb53d20532e41fb8b6b0e20d Mon Sep 17 00:00:00 2001 From: Prince Yadav <66916296+prince-0408@users.noreply.github.com> Date: Tue, 1 Sep 2026 19:02:43 +0530 Subject: [PATCH 2/2] refactor: address review comments on KeyboardLayoutHandler --- .../java/be/scri/helpers/KeyboardLayoutHandler.kt | 4 ++-- .../java/be/scri/services/GeneralKeyboardIME.kt | 12 ++---------- .../services/GeneralKeyboardIMEInputTypeTest.kt | 13 +++++++------ 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/app/src/keyboards/java/be/scri/helpers/KeyboardLayoutHandler.kt b/app/src/keyboards/java/be/scri/helpers/KeyboardLayoutHandler.kt index 738e2a0a3..6d673716e 100644 --- a/app/src/keyboards/java/be/scri/helpers/KeyboardLayoutHandler.kt +++ b/app/src/keyboards/java/be/scri/helpers/KeyboardLayoutHandler.kt @@ -11,7 +11,7 @@ import be.scri.models.ScribeState import be.scri.services.GeneralKeyboardIME private const val DATA_SIZE_2 = 2 -private const val DATA_CONSTANT_3 = 3 +private const val DATA_SIZE_3 = 3 /** * Encapsulates keyboard XML layout resolution, symbol layout mapping, @@ -65,7 +65,7 @@ class KeyboardLayoutHandler( } else { when (dataSize) { DATA_SIZE_2 -> R.xml.conjugate_view_2x1 - DATA_CONSTANT_3 -> R.xml.conjugate_view_1x3 + DATA_SIZE_3 -> R.xml.conjugate_view_1x3 else -> R.xml.conjugate_view_2x2 } } diff --git a/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt index bd4f45a02..2d2b7719f 100644 --- a/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt @@ -279,13 +279,6 @@ abstract class GeneralKeyboardIME( internal const val MAX_TEXT_LENGTH = 1000 const val COMMIT_TEXT_CURSOR_POSITION = 1 internal const val CUSTOM_CURSOR = "│" // special tall cursor character - - internal fun shouldUseNumericKeyboard(inputType: Int): Boolean = KeyboardLayoutHandler.shouldUseNumericKeyboard(inputType) - - internal fun getKeyboardLayoutXMLForInputType( - inputType: Int, - letterKeyboardLayoutXML: Int, - ): Int = KeyboardLayoutHandler.getKeyboardLayoutXMLForInputType(inputType, letterKeyboardLayoutXML) } // MARK: Lifecycle Methods @@ -441,9 +434,9 @@ abstract class GeneralKeyboardIME( // This setter triggers the logic in the property override if not shadowed. hasTextBeforeCursor = currentInputConnection?.getTextBeforeCursor(1, 0)?.isNotEmpty() == true - isNumericKeyboardActive = shouldUseNumericKeyboard(attribute.inputType) + isNumericKeyboardActive = KeyboardLayoutHandler.shouldUseNumericKeyboard(attribute.inputType) keyboardMode = if (isNumericKeyboardActive) keyboardSymbols else keyboardLetters - val keyboardXml = getKeyboardLayoutXMLForInputType(attribute.inputType, getKeyboardLayoutXML()) + val keyboardXml = KeyboardLayoutHandler.getKeyboardLayoutXMLForInputType(attribute.inputType, getKeyboardLayoutXML()) loadLanguageData() @@ -1984,7 +1977,6 @@ abstract class GeneralKeyboardIME( override fun recreateKeyboard() = layoutHandler.recreateKeyboard() - val isFloatingMode: Boolean get() = floatingKeyboardHandler.isFloatingMode diff --git a/app/src/testKeyboards/kotlin/be/scri/services/GeneralKeyboardIMEInputTypeTest.kt b/app/src/testKeyboards/kotlin/be/scri/services/GeneralKeyboardIMEInputTypeTest.kt index 797167697..abe7b691a 100644 --- a/app/src/testKeyboards/kotlin/be/scri/services/GeneralKeyboardIMEInputTypeTest.kt +++ b/app/src/testKeyboards/kotlin/be/scri/services/GeneralKeyboardIMEInputTypeTest.kt @@ -4,6 +4,7 @@ package be.scri.services import android.text.InputType import be.scri.R +import be.scri.helpers.KeyboardLayoutHandler import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue @@ -14,26 +15,26 @@ class GeneralKeyboardIMEInputTypeTest { fun shouldUseNumericKeyboard_returnsTrueForNumberInputs() { val inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL - assertTrue(GeneralKeyboardIME.shouldUseNumericKeyboard(inputType)) + assertTrue(KeyboardLayoutHandler.shouldUseNumericKeyboard(inputType)) } @Test fun shouldUseNumericKeyboard_returnsTrueForDateTimeInputs() { val inputType = InputType.TYPE_CLASS_DATETIME or InputType.TYPE_DATETIME_VARIATION_DATE - assertTrue(GeneralKeyboardIME.shouldUseNumericKeyboard(inputType)) + assertTrue(KeyboardLayoutHandler.shouldUseNumericKeyboard(inputType)) } @Test fun shouldUseNumericKeyboard_returnsTrueForPhoneInputs() { - assertTrue(GeneralKeyboardIME.shouldUseNumericKeyboard(InputType.TYPE_CLASS_PHONE)) + assertTrue(KeyboardLayoutHandler.shouldUseNumericKeyboard(InputType.TYPE_CLASS_PHONE)) } @Test fun shouldUseNumericKeyboard_returnsFalseForTextInputs() { val inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS - assertFalse(GeneralKeyboardIME.shouldUseNumericKeyboard(inputType)) + assertFalse(KeyboardLayoutHandler.shouldUseNumericKeyboard(inputType)) } @Test @@ -42,7 +43,7 @@ class GeneralKeyboardIMEInputTypeTest { assertEquals( R.xml.keys_numeric, - GeneralKeyboardIME.getKeyboardLayoutXMLForInputType(inputType, R.xml.keys_letters_english), + KeyboardLayoutHandler.getKeyboardLayoutXMLForInputType(inputType, R.xml.keys_letters_english), ) } @@ -52,7 +53,7 @@ class GeneralKeyboardIMEInputTypeTest { assertEquals( R.xml.keys_letters_english, - GeneralKeyboardIME.getKeyboardLayoutXMLForInputType(inputType, R.xml.keys_letters_english), + KeyboardLayoutHandler.getKeyboardLayoutXMLForInputType(inputType, R.xml.keys_letters_english), ) } }