differentiate between permanent and 1 time caps lock

This commit is contained in:
tibbi 2022-01-12 23:00:41 +01:00
parent 3714a61ad7
commit f3045fc68a
4 changed files with 75 additions and 41 deletions

View File

@ -0,0 +1,5 @@
package com.simplemobiletools.keyboard.helpers
const val SHIFT_OFF = 0
const val SHIFT_ON_ONE_CHAR = 1
const val SHIFT_ON_PERMANENT = 2

View File

@ -67,7 +67,7 @@ class MyKeyboard {
protected var mDefaultVerticalGap = 0 protected var mDefaultVerticalGap = 0
/** Is the keyboard in the shifted state */ /** Is the keyboard in the shifted state */
var isShifted = false var shiftState = SHIFT_OFF
/** Key instance for the shift key, if present */ /** Key instance for the shift key, if present */
private val mShiftKeys = arrayOf<Key?>(null, null) private val mShiftKeys = arrayOf<Key?>(null, null)
@ -562,13 +562,13 @@ class MyKeyboard {
// also recalculate the vertical sizes/positions when we get this resize call. // also recalculate the vertical sizes/positions when we get this resize call.
} }
fun setShifted(shiftState: Boolean): Boolean { fun setShifted(shiftState: Int): Boolean {
for (shiftKey in mShiftKeys) { for (shiftKey in mShiftKeys) {
shiftKey?.on = shiftState shiftKey?.on = shiftState > SHIFT_OFF
} }
if (isShifted != shiftState) { if (this.shiftState != shiftState) {
isShifted = shiftState this.shiftState = shiftState
return true return true
} }

View File

@ -7,13 +7,18 @@ import android.view.View
import com.simplemobiletools.commons.extensions.performHapticFeedback import com.simplemobiletools.commons.extensions.performHapticFeedback
import com.simplemobiletools.keyboard.R import com.simplemobiletools.keyboard.R
import com.simplemobiletools.keyboard.helpers.MyKeyboard import com.simplemobiletools.keyboard.helpers.MyKeyboard
import com.simplemobiletools.keyboard.helpers.SHIFT_OFF
import com.simplemobiletools.keyboard.helpers.SHIFT_ON_ONE_CHAR
import com.simplemobiletools.keyboard.helpers.SHIFT_ON_PERMANENT
import com.simplemobiletools.keyboard.views.MyKeyboardView import com.simplemobiletools.keyboard.views.MyKeyboardView
// based on https://www.androidauthority.com/lets-build-custom-keyboard-android-832362/ // based on https://www.androidauthority.com/lets-build-custom-keyboard-android-832362/
class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionListener { class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionListener {
private var SHIFT_PERM_TOGGLE_SPEED = 500 // how quickly do we have to doubletap shift to enable permanent caps lock
private var keyboard: MyKeyboard? = null private var keyboard: MyKeyboard? = null
private var keyboardView: MyKeyboardView? = null private var keyboardView: MyKeyboardView? = null
private var caps = false private var lastShiftPressTS = 0L
override fun onCreateInputView(): View { override fun onCreateInputView(): View {
keyboardView = layoutInflater.inflate(R.layout.keyboard_view_keyboard, null) as MyKeyboardView keyboardView = layoutInflater.inflate(R.layout.keyboard_view_keyboard, null) as MyKeyboardView
@ -31,30 +36,46 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
override fun onKey(primaryCode: Int, keyCodes: IntArray?) { override fun onKey(primaryCode: Int, keyCodes: IntArray?) {
val inputConnection = currentInputConnection val inputConnection = currentInputConnection
if (inputConnection != null) { if (keyboard == null || inputConnection == null) {
when (primaryCode) { return
MyKeyboard.KEYCODE_DELETE -> { }
val selectedText = inputConnection.getSelectedText(0)
if (TextUtils.isEmpty(selectedText)) { when (primaryCode) {
inputConnection.deleteSurroundingText(1, 0) MyKeyboard.KEYCODE_DELETE -> {
} else { if (keyboard!!.shiftState == SHIFT_ON_ONE_CHAR) {
inputConnection.commitText("", 1) keyboard!!.shiftState = SHIFT_OFF
}
keyboard!!.isShifted = caps
keyboardView!!.invalidateAllKeys()
} }
MyKeyboard.KEYCODE_SHIFT -> {
caps = !caps val selectedText = inputConnection.getSelectedText(0)
keyboard!!.isShifted = caps if (TextUtils.isEmpty(selectedText)) {
keyboardView!!.invalidateAllKeys() inputConnection.deleteSurroundingText(1, 0)
} else {
inputConnection.commitText("", 1)
} }
MyKeyboard.KEYCODE_DONE -> inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)) keyboardView!!.invalidateAllKeys()
else -> { }
var code = primaryCode.toChar() MyKeyboard.KEYCODE_SHIFT -> {
if (Character.isLetter(code) && caps) { when {
code = Character.toUpperCase(code) keyboard!!.shiftState == SHIFT_ON_PERMANENT -> keyboard!!.shiftState = SHIFT_OFF
} System.currentTimeMillis() - lastShiftPressTS < SHIFT_PERM_TOGGLE_SPEED -> keyboard!!.shiftState = SHIFT_ON_PERMANENT
inputConnection.commitText(code.toString(), 1) keyboard!!.shiftState == SHIFT_ON_ONE_CHAR -> keyboard!!.shiftState = SHIFT_OFF
keyboard!!.shiftState == SHIFT_OFF -> keyboard!!.shiftState = SHIFT_ON_ONE_CHAR
}
lastShiftPressTS = System.currentTimeMillis()
keyboardView!!.invalidateAllKeys()
}
MyKeyboard.KEYCODE_DONE -> inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER))
else -> {
var code = primaryCode.toChar()
if (Character.isLetter(code) && keyboard!!.shiftState > SHIFT_OFF) {
code = Character.toUpperCase(code)
}
inputConnection.commitText(code.toString(), 1)
if (keyboard!!.shiftState == SHIFT_ON_ONE_CHAR) {
keyboard!!.shiftState = SHIFT_OFF
keyboardView!!.invalidateAllKeys()
} }
} }
} }

View File

@ -5,6 +5,7 @@ import android.content.Context
import android.graphics.* import android.graphics.*
import android.graphics.Paint.Align import android.graphics.Paint.Align
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.inputmethodservice.KeyboardView
import android.media.AudioManager import android.media.AudioManager
import android.os.Handler import android.os.Handler
import android.os.Message import android.os.Message
@ -18,6 +19,9 @@ import android.widget.PopupWindow
import android.widget.TextView import android.widget.TextView
import com.simplemobiletools.keyboard.R import com.simplemobiletools.keyboard.R
import com.simplemobiletools.keyboard.helpers.MyKeyboard import com.simplemobiletools.keyboard.helpers.MyKeyboard
import com.simplemobiletools.keyboard.helpers.SHIFT_OFF
import com.simplemobiletools.keyboard.helpers.SHIFT_ON_ONE_CHAR
import com.simplemobiletools.keyboard.helpers.SHIFT_ON_PERMANENT
import java.util.* import java.util.*
/** /**
@ -415,13 +419,11 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
* @return true if the shift key state changed, false if there was no change * @return true if the shift key state changed, false if there was no change
* @see KeyboardView.isShifted * @see KeyboardView.isShifted
*/ */
fun setShifted(shifted: Boolean): Boolean { fun setShifted(shiftState: Int) {
if (mKeyboard?.setShifted(shifted) == true) { if (mKeyboard?.setShifted(shiftState) == true) {
// The whole keyboard probably needs to be redrawn // The whole keyboard probably needs to be redrawn
invalidateAllKeys() invalidateAllKeys()
return true
} }
return false
} }
/** /**
@ -431,7 +433,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
* @see KeyboardView.setShifted * @see KeyboardView.setShifted
*/ */
fun isShifted(): Boolean { fun isShifted(): Boolean {
return mKeyboard?.isShifted ?: false return mKeyboard?.shiftState ?: SHIFT_OFF > SHIFT_OFF
} }
fun setPopupParent(v: View) { fun setPopupParent(v: View) {
@ -456,7 +458,7 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
private fun adjustCase(label: CharSequence): CharSequence? { private fun adjustCase(label: CharSequence): CharSequence? {
var newLabel: CharSequence? = label var newLabel: CharSequence? = label
if (newLabel != null && newLabel.isNotEmpty() && mKeyboard!!.isShifted && newLabel.length < 3 && Character.isLowerCase(newLabel[0])) { if (newLabel != null && newLabel.isNotEmpty() && mKeyboard!!.shiftState > SHIFT_OFF && newLabel.length < 3 && Character.isLowerCase(newLabel[0])) {
newLabel = newLabel.toString().toUpperCase() newLabel = newLabel.toString().toUpperCase()
} }
return newLabel return newLabel
@ -598,12 +600,12 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
) )
// Turn off drop shadow // Turn off drop shadow
paint.setShadowLayer(0f, 0f, 0f, 0) paint.setShadowLayer(0f, 0f, 0f, 0)
} else if (key.icon != null) { } else if (key.icon != null && mKeyboard != null) {
if (key.codes.size == 1 && key.codes.contains(-1)) { if (key.codes.size == 1 && key.codes.contains(-1)) {
val drawableId = if (isShifted()) { val drawableId = when (mKeyboard!!.shiftState) {
R.drawable.ic_caps_vector SHIFT_OFF -> R.drawable.ic_caps_outline_vector
} else { SHIFT_ON_ONE_CHAR -> R.drawable.ic_caps_vector
R.drawable.ic_caps_outline_vector else -> R.drawable.ic_caps_underlined_vector
} }
key.icon = resources.getDrawable(drawableId) key.icon = resources.getDrawable(drawableId)
} }
@ -808,7 +810,11 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
mPreviewText!!.setCompoundDrawables(null, null, null, bottomDrawable) mPreviewText!!.setCompoundDrawables(null, null, null, bottomDrawable)
} else { } else {
mPreviewText!!.setCompoundDrawables(null, null, null, null) mPreviewText!!.setCompoundDrawables(null, null, null, null)
mPreviewText!!.text = getPreviewText(key) try {
mPreviewText!!.text = getPreviewText(key)
} catch (ignored: Exception) {
}
if (key.label.length > 1 && key.codes.size < 2) { if (key.label.length > 1 && key.codes.size < 2) {
mPreviewText!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyTextSize.toFloat()) mPreviewText!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyTextSize.toFloat())
mPreviewText!!.typeface = Typeface.DEFAULT_BOLD mPreviewText!!.typeface = Typeface.DEFAULT_BOLD
@ -1020,7 +1026,9 @@ class MyKeyboardView @JvmOverloads constructor(context: Context, attrs: Attribut
val x = mPopupX + mMiniKeyboardContainer!!.paddingRight + mCoordinates[0] val x = mPopupX + mMiniKeyboardContainer!!.paddingRight + mCoordinates[0]
val y = mPopupY + mMiniKeyboardContainer!!.paddingBottom + mCoordinates[1] val y = mPopupY + mMiniKeyboardContainer!!.paddingBottom + mCoordinates[1]
mMiniKeyboard!!.setPopupOffset(if (x < 0) 0 else x, y) mMiniKeyboard!!.setPopupOffset(if (x < 0) 0 else x, y)
mMiniKeyboard!!.setShifted(isShifted())
val miniShiftStatus = if (isShifted()) SHIFT_ON_PERMANENT else SHIFT_OFF
mMiniKeyboard!!.setShifted(miniShiftStatus)
mPopupKeyboard.contentView = mMiniKeyboardContainer mPopupKeyboard.contentView = mMiniKeyboardContainer
mPopupKeyboard.width = mMiniKeyboardContainer!!.measuredWidth mPopupKeyboard.width = mMiniKeyboardContainer!!.measuredWidth
mPopupKeyboard.height = mMiniKeyboardContainer!!.measuredHeight mPopupKeyboard.height = mMiniKeyboardContainer!!.measuredHeight