Skip to content

Commit 2646427

Browse files
committed
now number row is replaced for SpecialKeyLayout.kt
improved code design (i hope)
1 parent ab47742 commit 2646427

File tree

6 files changed

+143
-62
lines changed

6 files changed

+143
-62
lines changed

app/src/main/java/com/soobakjonmat/customlayoutkeyboard/MainKeyboardService.kt

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,24 @@ class MainKeyboardService : InputMethodService() {
3232
private lateinit var keyboardRoot: FrameLayout
3333
lateinit var mainKeyboardView: LinearLayout
3434
lateinit var phoneNumKeyboardView: LinearLayout
35-
private lateinit var englishLayout: EnglishLayout
36-
private lateinit var koreanLayout: KoreanLayout
37-
private lateinit var specialKeyLayout: SpecialKeyLayout
38-
private lateinit var phoneNumberLayout: PhoneNumberLayout
3935

40-
private lateinit var languageLayouts: Array<LanguageLayout>
36+
private val languageMode = mapOf("Special" to 0, "English" to 1, "Korean" to 2)
37+
private lateinit var standardLayouts: Array<KeyboardLayout>
38+
private lateinit var phoneNumberLayout: PhoneNumberLayout
4139

4240
var rapidTextDeleteInterval: Long = 200 // in milliseconds
4341
val gestureMinDist = 120
4442

4543
private val numbers = arrayOf("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
46-
private val numBtnSubTexts = arrayOf("!", "@", "#", "$", "%", "^", "&", "*", "(", ")")
47-
private val combinedNums = mutableListOf<SpannableString>()
48-
44+
val numBtnSubTexts = arrayOf("!", "@", "#", "$", "%", "^", "&", "*", "(", ")")
4945
val subTextLetterList = listOf(
50-
arrayOf("!", "(", ")", "\\", "|", "[", "]", "{", "}"),
46+
arrayOf("", "", "", "\\", "|", "[", "]", "{", "}"),
5147
arrayOf("", "", "`", "~", "-", "_", ":", ";", "\"", "'"),
52-
arrayOf("<", ">", "=", "+", "*", "/", "?")
48+
arrayOf("", "<", ">", "=", "+", "/", "?")
5349
)
50+
private val combinedNums = mutableListOf<SpannableString>()
51+
lateinit var numberRow: LinearLayout
52+
5453
var subtextColor = 0
5554

5655
private lateinit var numBtns: Array<Button>
@@ -70,6 +69,7 @@ class MainKeyboardService : InputMethodService() {
7069
private var returnKeyImageForward: VectorDrawableCompat? = null
7170
private var returnKeyImageReturn: VectorDrawableCompat? = null
7271
private var returnKeyImageTab: VectorDrawableCompat? = null
72+
7373
var currReturnKeyImage: VectorDrawableCompat? = null
7474

7575
private val searchIconActionList = arrayOf(
@@ -89,7 +89,7 @@ class MainKeyboardService : InputMethodService() {
8989
)
9090
var currIMEOptions = 0
9191

92-
private var mode = 1
92+
private var mode = languageMode["English"]!!
9393
private var lastDownSpacebarX = 0f
9494
private var lastCursorPos = 0
9595

@@ -106,6 +106,12 @@ class MainKeyboardService : InputMethodService() {
106106
mainKeyboardView = layoutInflater.inflate(R.layout.main_keyboardview, null) as LinearLayout
107107
phoneNumKeyboardView = layoutInflater.inflate(R.layout.phone_number_keyboardview, null) as LinearLayout
108108

109+
specialKeyBtn = mainKeyboardView.findViewById(R.id.special_key)
110+
commaBtn = mainKeyboardView.findViewById(R.id.comma)
111+
spacebarBtn = mainKeyboardView.findViewById(R.id.spacebar)
112+
fullStopBtn = mainKeyboardView.findViewById(R.id.full_stop)
113+
returnKeyBtn = mainKeyboardView.findViewById(R.id.return_key)
114+
109115
val vm = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
110116
vibrator = vm.defaultVibrator
111117

@@ -120,8 +126,13 @@ class MainKeyboardService : InputMethodService() {
120126
returnKeyImageForward = VectorDrawableCompat.create(resources, R.drawable.ic_outline_arrow_forward_24, null)
121127

122128
// number buttons
123-
val numberRow = mainKeyboardView.findViewById<LinearLayout>(R.id.number_row)
124-
129+
numberRow = LinearLayout(mainKeyboardView.context)
130+
numberRow.layoutParams = LinearLayout.LayoutParams(
131+
LinearLayout.LayoutParams.MATCH_PARENT,
132+
0,
133+
1f
134+
)
135+
numberRow.orientation = LinearLayout.HORIZONTAL
125136
numBtns = Array(numbers.size) { Button(ContextThemeWrapper(this, R.style.Theme_LetterBtn)) }
126137
numBtnPreviewPopupArr = Array(numbers.size) { PopupWindow(ContextThemeWrapper(this, R.style.Theme_TransparentBackground)) }
127138

@@ -171,7 +182,6 @@ class MainKeyboardService : InputMethodService() {
171182
}
172183

173184
// special key
174-
specialKeyBtn = mainKeyboardView.findViewById(R.id.special_key)
175185
specialKeyBtn.setOnClickListener {
176186
vibrate()
177187
if (mode != 0) {
@@ -186,8 +196,6 @@ class MainKeyboardService : InputMethodService() {
186196
}
187197

188198
// spacebar
189-
spacebarBtn = mainKeyboardView.findViewById(R.id.spacebar)
190-
191199
spacebarBtn.setOnTouchListener { btn, motionEvent ->
192200
val action = motionEvent.action
193201
if (action == MotionEvent.ACTION_DOWN) {
@@ -224,23 +232,20 @@ class MainKeyboardService : InputMethodService() {
224232
}
225233

226234
// comma
227-
commaBtn = mainKeyboardView.findViewById(R.id.comma)
228235
commaBtn.setTextSize(TypedValue.COMPLEX_UNIT_SP, resources.getFloat(R.dimen.default_text_size))
229236
commaBtn.setOnClickListener {
230237
vibrate()
231238
resetAndFinishComposing()
232239
currentInputConnection.commitText(",", 1)
233240
}
234241
// full stop
235-
fullStopBtn = mainKeyboardView.findViewById(R.id.full_stop)
236242
fullStopBtn.setTextSize(TypedValue.COMPLEX_UNIT_SP, resources.getFloat(R.dimen.default_text_size))
237243
fullStopBtn.setOnClickListener {
238244
vibrate()
239245
resetAndFinishComposing()
240246
currentInputConnection.commitText(".", 1)
241247
}
242248
// return key
243-
returnKeyBtn = mainKeyboardView.findViewById(R.id.return_key)
244249
returnKeyBtn.setOnClickListener {
245250
vibrate()
246251
resetAndFinishComposing()
@@ -252,17 +257,13 @@ class MainKeyboardService : InputMethodService() {
252257
}
253258
}
254259

255-
englishLayout = EnglishLayout(this)
256-
englishLayout.init()
257-
koreanLayout = KoreanLayout(this)
258-
koreanLayout.init()
259-
specialKeyLayout = SpecialKeyLayout(this)
260-
specialKeyLayout.init()
260+
standardLayouts = arrayOf(SpecialKeyLayout(this), EnglishLayout(this), KoreanLayout(this))
261+
for (layout in standardLayouts) {
262+
layout.init()
263+
}
261264
phoneNumberLayout = PhoneNumberLayout(this)
262265
phoneNumberLayout.init()
263266

264-
languageLayouts = arrayOf(englishLayout, koreanLayout)
265-
266267
// init layout
267268
changeLayout()
268269
}
@@ -292,7 +293,6 @@ class MainKeyboardService : InputMethodService() {
292293
if ((currIMEOptions and EditorInfo.IME_FLAG_NO_ENTER_ACTION) == EditorInfo.IME_FLAG_NO_ENTER_ACTION) {
293294
currReturnKeyImage = returnKeyImageReturn
294295
}
295-
296296
returnKeyBtn.setImageDrawable(currReturnKeyImage)
297297

298298
keyboardRoot = if (mainKeyboardView.parent != null) {
@@ -301,7 +301,7 @@ class MainKeyboardService : InputMethodService() {
301301
phoneNumKeyboardView.parent as FrameLayout
302302
}
303303
// if inputType is phone number
304-
if (editorInfo?.inputType?.and(InputType.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_PHONE) {
304+
if (editorInfo?.inputType?.and(InputType.TYPE_MASK_CLASS) == (InputType.TYPE_CLASS_PHONE or InputType.TYPE_CLASS_NUMBER)) {
305305
if (keyboardRoot.children.contains(mainKeyboardView)) {
306306
keyboardRoot.removeView(mainKeyboardView)
307307
phoneNumberLayout.updateReturnKeyImage()
@@ -322,7 +322,7 @@ class MainKeyboardService : InputMethodService() {
322322

323323
override fun onUpdateCursorAnchorInfo(cursorAnchorInfo: CursorAnchorInfo) {
324324
val currPos = cursorAnchorInfo.selectionStart
325-
if ((currPos != lastCursorPos + 1 || !koreanLayout.hangulAssembler.cursorMovedBySystem) && currPos != lastCursorPos) {
325+
if ((currPos != lastCursorPos + 1 || !(standardLayouts[languageMode["Korean"]!!] as KoreanLayout).hangulAssembler.cursorMovedBySystem) && currPos != lastCursorPos) {
326326
resetAndFinishComposing()
327327
}
328328
lastCursorPos = currPos
@@ -364,9 +364,8 @@ class MainKeyboardService : InputMethodService() {
364364
}
365365
numBtns[i].text = combinedNums[i]
366366
}
367-
for (layout in languageLayouts) {
368-
layout.updateSubtextColor()
369-
}
367+
(standardLayouts[languageMode["English"]!!] as LanguageLayout).updateSubtextColor()
368+
(standardLayouts[languageMode["Korean"]!!] as LanguageLayout).updateSubtextColor()
370369
}
371370

372371
fun deleteByWord(direction: Int): Boolean {
@@ -426,34 +425,32 @@ class MainKeyboardService : InputMethodService() {
426425

427426
private fun changeLayout() {
428427
resetAndFinishComposing()
429-
// delete middle rows
430-
if (mainKeyboardView.childCount > 2) {
431-
for (i in 0 until mainKeyboardView.childCount-2) {
432-
mainKeyboardView.removeViewAt(1)
428+
if (mainKeyboardView.childCount > 1) { // check if this is initial layout insert call
429+
// delete remove every row except control row
430+
for (i in 0 until mainKeyboardView.childCount-1) {
431+
mainKeyboardView.removeViewAt(0)
433432
}
434433
}
434+
standardLayouts[mode].insertLayout()
435435
when (mode) {
436436
// special key layout
437-
0 -> {
438-
specialKeyLayout.insertLetterBtns()
437+
languageMode["Special"]!! -> {
439438
spacebarBtn.text = getString(R.string.spacebar_text_special_key)
440439
}
441440
// english layout
442-
1 -> {
443-
englishLayout.insertLetterBtns()
441+
languageMode["English"]!! -> {
444442
spacebarBtn.text = getString(R.string.spacebar_text_english)
445443
}
446444
// korean layout
447-
2 -> {
448-
koreanLayout.insertLetterBtns()
445+
languageMode["Korean"]!! -> {
449446
spacebarBtn.text = getString(R.string.spacebar_text_korean)
450447
}
451448
}
452449
}
453450

454451
fun resetAndFinishComposing() {
455-
if (mode == 2) {
456-
koreanLayout.hangulAssembler.reset()
452+
if (mode == languageMode["Korean"]) {
453+
(standardLayouts[languageMode["Korean"]!!] as KoreanLayout).hangulAssembler.reset()
457454
}
458455
if (currentInputConnection != null) {
459456
currentInputConnection.finishComposingText()

app/src/main/java/com/soobakjonmat/customlayoutkeyboard/layout/KeyboardLayout.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import android.widget.LinearLayout
1111
import android.widget.PopupWindow
1212
import com.soobakjonmat.customlayoutkeyboard.MainKeyboardService
1313
import com.soobakjonmat.customlayoutkeyboard.R
14-
import java.util.*
1514
import kotlin.concurrent.timerTask
15+
import java.util.Timer
1616

1717
abstract class KeyboardLayout(protected val mainKeyboardService: MainKeyboardService) {
1818
protected val mainKeyboardView = mainKeyboardService.mainKeyboardView
@@ -38,12 +38,7 @@ abstract class KeyboardLayout(protected val mainKeyboardService: MainKeyboardSer
3838
}
3939
}
4040

41-
fun insertLetterBtns() {
42-
for (i in rowList.size - 1 downTo 0) {
43-
mainKeyboardView.addView(rowList[i], 1)
44-
}
45-
}
46-
41+
abstract fun insertLayout()
4742
abstract inner class KeyboardGestureListener(
4843
protected val i: Int,
4944
protected val j: Int

app/src/main/java/com/soobakjonmat/customlayoutkeyboard/layout/KoreanLayout.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import androidx.core.view.size
2020
import com.soobakjonmat.customlayoutkeyboard.MainKeyboardService
2121
import com.soobakjonmat.customlayoutkeyboard.HangulAssembler
2222
import com.soobakjonmat.customlayoutkeyboard.R
23-
import java.util.*
2423

2524
class KoreanLayout(mainKeyboardService: MainKeyboardService) : LanguageLayout(mainKeyboardService) {
2625
val hangulAssembler = HangulAssembler(mainKeyboardService)

app/src/main/java/com/soobakjonmat/customlayoutkeyboard/layout/LanguageLayout.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ abstract class LanguageLayout(mainKeyboardService: MainKeyboardService) : Keyboa
4949
}
5050
}
5151

52+
override fun insertLayout() {
53+
for (i in rowList.size - 1 downTo 0) {
54+
mainKeyboardView.addView(rowList[i], 0)
55+
}
56+
mainKeyboardView.addView(mainKeyboardService.numberRow, 0)
57+
}
58+
5259
protected abstract fun setToUppercase()
5360

5461
protected abstract fun setToLowercase()

app/src/main/java/com/soobakjonmat/customlayoutkeyboard/layout/SpecialKeyLayout.kt

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import android.annotation.SuppressLint
44
import android.util.TypedValue
55
import android.view.ContextThemeWrapper
66
import android.view.GestureDetector
7+
import android.view.GestureDetector.OnGestureListener
8+
import android.view.Gravity
79
import android.view.MotionEvent
810
import android.widget.Button
911
import android.widget.LinearLayout
@@ -14,16 +16,55 @@ import androidx.core.view.setPadding
1416
import androidx.core.view.size
1517
import com.soobakjonmat.customlayoutkeyboard.MainKeyboardService
1618
import com.soobakjonmat.customlayoutkeyboard.R
17-
import java.util.*
1819

1920
class SpecialKeyLayout(mainKeyboardService: MainKeyboardService) : KeyboardLayout(mainKeyboardService) {
2021

2122
val subTextLetterList = mainKeyboardService.subTextLetterList
23+
private lateinit var topBtns: Array<Button>
24+
private lateinit var topRow: LinearLayout
25+
private val topPreviewPopupList = Array(mainKeyboardService.numBtnSubTexts.size) { PopupWindow(ContextThemeWrapper(mainKeyboardView.context, R.style.Theme_TransparentBackground)) }
2226

2327
@SuppressLint("ClickableViewAccessibility")
2428
override fun init() {
2529
super.init()
2630

31+
topRow = LinearLayout(mainKeyboardView.context)
32+
topRow.layoutParams = LinearLayout.LayoutParams(
33+
LinearLayout.LayoutParams.MATCH_PARENT,
34+
0,
35+
1f
36+
)
37+
topRow.orientation = LinearLayout.HORIZONTAL
38+
topBtns = Array(mainKeyboardService.numBtnSubTexts.size) { Button(ContextThemeWrapper(mainKeyboardView.context, R.style.Theme_LetterBtn)) }
39+
for (i in mainKeyboardService.numBtnSubTexts.indices) {
40+
topBtns[i].layoutParams = LinearLayout.LayoutParams(
41+
0,
42+
LinearLayout.LayoutParams.MATCH_PARENT,
43+
1f
44+
)
45+
topBtns[i].setPadding(0)
46+
47+
val gestureDetector = GestureDetector(mainKeyboardService, TopRowGestureListener(i))
48+
topBtns[i].setOnTouchListener { _, event ->
49+
if (event.action == MotionEvent.ACTION_UP) {
50+
topPreviewPopupList[i].dismiss()
51+
}
52+
gestureDetector.onTouchEvent(event)
53+
}
54+
topBtns[i].text = mainKeyboardService.numBtnSubTexts[i]
55+
56+
topRow.addView(topBtns[i])
57+
58+
topPreviewPopupList[i].isTouchable = false
59+
topPreviewPopupList[i].contentView = TextView(ContextThemeWrapper(mainKeyboardView.context, R.style.Theme_PreviewPopupTextView))
60+
(topPreviewPopupList[i].contentView as TextView).background = ResourcesCompat.getDrawable(resources, R.drawable.preview_popup_background, ContextThemeWrapper(mainKeyboardView.context, R.style.Theme_PreviewPopupTextView).theme)
61+
(topPreviewPopupList[i].contentView as TextView).text = mainKeyboardService.numBtnSubTexts[i]
62+
(topPreviewPopupList[i].contentView as TextView).elevation = 8f
63+
(topPreviewPopupList[i].contentView as TextView).setPadding(resources.getInteger(R.integer.english_preview_popup_text_padding), 0, 0, 0)
64+
(topPreviewPopupList[i].contentView as TextView).setTextSize(TypedValue.COMPLEX_UNIT_SP, resources.getFloat(R.dimen.preview_popup_text_size))
65+
topPreviewPopupList[i].setBackgroundDrawable(null)
66+
}
67+
2768
rowList = Array(subTextLetterList.size) { LinearLayout(mainKeyboardView.context) }
2869

2970
for (i in subTextLetterList.indices) {
@@ -99,6 +140,56 @@ class SpecialKeyLayout(mainKeyboardService: MainKeyboardService) : KeyboardLayou
99140
rowList[rowList.size-1].addView(backspaceBtn, rowList[rowList.size-1].size)
100141
}
101142

143+
override fun insertLayout() {
144+
for (i in rowList.size - 1 downTo 0) {
145+
mainKeyboardView.addView(rowList[i], 0)
146+
}
147+
mainKeyboardView.addView(topRow, 0)
148+
}
149+
150+
private inner class TopRowGestureListener(val i: Int) : OnGestureListener {
151+
override fun onDown(p0: MotionEvent): Boolean {
152+
topBtns[i].isPressed = true
153+
val loc = IntArray(2)
154+
topBtns[i].getLocationInWindow(loc)
155+
topPreviewPopupList[i].showAtLocation(topBtns[i], Gravity.NO_GRAVITY, 0, 0)
156+
topPreviewPopupList[i].update(loc[0], loc[1]-128, 128, 128, false)
157+
mainKeyboardService.vibrate()
158+
return true
159+
}
160+
161+
override fun onShowPress(p0: MotionEvent) {}
162+
override fun onLongPress(p0: MotionEvent) {}
163+
164+
override fun onSingleTapUp(p0: MotionEvent): Boolean {
165+
topBtns[i].isPressed = false
166+
topPreviewPopupList[i].dismiss()
167+
mainKeyboardService.currentInputConnection.commitText(mainKeyboardService.numBtnSubTexts[i], 1)
168+
return true
169+
}
170+
171+
override fun onScroll(p0: MotionEvent, p1: MotionEvent, p2: Float, p3: Float): Boolean {
172+
topBtns[i].isPressed = false
173+
topPreviewPopupList[i].dismiss()
174+
return true
175+
}
176+
177+
override fun onFling(p0: MotionEvent, p1: MotionEvent, p2: Float, p3: Float): Boolean {
178+
topBtns[i].isPressed = false
179+
topPreviewPopupList[i].dismiss()
180+
if (p0.rawX - p1.rawX > gestureMinDist) {
181+
mainKeyboardService.deleteByWord(-1)
182+
return true
183+
}
184+
else if (p1.rawX - p0.rawX > gestureMinDist) {
185+
mainKeyboardService.deleteByWord(1)
186+
return true
187+
}
188+
return false
189+
}
190+
191+
}
192+
102193
private inner class SpecialKeyGestureListener(i: Int, j: Int) : KeyboardGestureListener(i, j) {
103194
override fun onSingleTapUp(event: MotionEvent): Boolean {
104195
super.onSingleTapUp(event)

0 commit comments

Comments
 (0)