The problem with the above solution, as commented is that
if I press other key (e.g. key A) and move my finger to the key SHIFT, the preview icon still popup
To counter this, I had to extend the KeyboardView class
Disclaimer - The following contains reflection api
Here is the modified Keyboard class
import android.content.Context
import android.inputmethodservice.KeyboardView
import android.os.Build
import android.support.annotation.RequiresApi
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.TextView
import com.continental.testapplication.utils.dpToPx
import java.lang.reflect.Method
class ModifiedKeyboardView :KeyboardView{
constructor(context: Context, attrs: AttributeSet):super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr:Int):super(context, attrs, defStyleAttr)
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
constructor(context: Context, attrs: AttributeSet, defStyleAttr:Int, defStyleRes:Int):
super(context, attrs, defStyleAttr, defStyleRes)
/**
* Return true, if preview is to be shown, false otherwise. If not implemented,
* the preview is going to be shown.....
*/
var keyPreviewIndexListener:((Int)->Boolean) ?= null
private val findKeyIndicesMethod:Method = KeyboardView::class.java.getDeclaredMethod(
"getKeyIndices",Int::class.java,Int::class.java, (IntArray::class).java).also {
it.isAccessible = true
}
private val previewText:TextView = KeyboardView::class.java.getDeclaredField(
"mPreviewText").let {
it.isAccessible = true
it.get(this) as TextView
}
override fun onTouchEvent(me: MotionEvent?): Boolean {
if(me == null) return super.onTouchEvent(me)
when(me.action){
MotionEvent.ACTION_DOWN -> isPreviewEnabled = true
MotionEvent.ACTION_MOVE -> {
val touchX = me.x - paddingLeft
var touchY = me.y.toInt() - paddingTop
val verticalCorrection = dpToPx(14f, context)
if (touchY >= -verticalCorrection)
touchY += verticalCorrection.toInt()
val keyIndex:Int = findKeyIndicesMethod.invoke(this, touchX.toInt(), touchY.toInt(), null) as Int
isPreviewEnabled = keyPreviewIndexListener?.invoke(keyIndex)?:true
if(!isPreviewEnabled){
previewText.visibility = View.INVISIBLE
}
}
}
return super.onTouchEvent(me)
}
}
Paste it as is.
Next, in the class where you are manipulating the keyboard,
keyboardView.keyPreviewIndexListener = {
it != spaceIndex && it != doneIndex && it != deleteIndex && it != `your_custom_index`
}
To find the indexes you can just do the following
doneIndex = keyboardView.keyboard.keys.indexOfFirst {
it.codes[0] == Keyboard.KEYCODE_DONE
}
This will prevent the movement. Please append the other solution also.
i.e
override fun onPress(primaryCode: Int) {
Log.e("onPress", primaryCode.toString())
checkAndActivatePreview(primaryCode)
}
override fun onRelease(primaryCode: Int) {
Log.e("onRelease", primaryCode.toString())
deactivatePreview()
}
private fun checkAndActivatePreview(primaryCode: Int) {
keyboard.isPreviewEnabled =
(primaryCode != `your_custom_code`
&& primaryCode != SPACE_KEY_CODE && primaryCode != Keyboard.KEYCODE_DELETE
&& primaryCode != Keyboard.KEYCODE_DONE)
}