7

How to remove repeating keys, key preview of Android Custom Keyboard. I used following method to remove key preview of the keys that I want. But that method is not working for repeatable keys. (android:isRepeatable="true") If the key is not repeatable, following method is working.

delete key xml

<Key android:codes="-5"
        android:keyWidth="13%p"
        android:keyIcon="@drawable/ic_key_delete_white"
        android:keyBackground="@color/dark_key_background"
        android:isRepeatable="true"
        android:horizontalGap="3.5%p"
        android:keyEdgeFlags="right"/>

Input method service Class

@Override
public void onPress(int primaryCode) {
    if (primaryCode == -1 
            || primaryCode == -5){
        kv.setPreviewEnabled(false);
    }
}

@Override
public void onRelease(int primaryCode) {
    if(primaryCode == -1 
            || primaryCode == -5){
        kv.setPreviewEnabled(true);
    }
}
Arvin Jayanake
  • 1,475
  • 3
  • 14
  • 26

4 Answers4

4

Revers setPreviewEnabled flag..

public void onCreate() {

    mInputView.setPreviewEnabled(false);

}

public void onPress(int primaryCode) {
    if (primaryCode==-1||primaryCode==-2||primaryCode==-5||primaryCode==-4){

    } else {
       mInputView.setPreviewEnabled(true);
    }
}

public void onRelease(int primaryCode) {
    mInputView.setPreviewEnabled(false);
}
James Hong
  • 67
  • 8
0

In following example we have two repeatable keys (Space and Delete)

STEP 1: set PreviewEnabled to "false" in onCreateInputView() :

kv.setPreviewEnabled(false);

STEP 2: add following if-else statement in onPress() :

public void onPress(int primaryCode) 
{
   if (!(primaryCode==32||primaryCode==Keyboard.KEYCODE_DELETE))
   {
       kv.setPreviewEnabled(true);
   }
   else
   {
       kv.setPreviewEnabled(false);
   }
}

STEP 3: set PreviewEnabled to "false" in onRelease() :

public void onRelease(int primaryCode) 
{
   kv.setPreviewEnabled(false);
}
0

I have written an answer on this, check it out here https://stackoverflow.com/a/53446268/5689605

To put it here,

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)
    }
Debanjan
  • 2,817
  • 2
  • 24
  • 43
0

If key is repeatable OnRelease method will be called as soon as OnPress called. Use this code

@Override
public void onPress(int primaryCode) {
    if (primaryCode == -1 
            || primaryCode == -5){
        kv.setPreviewEnabled(false);
    }else{
        kv.setPreviewEnabled(true);
    }
}

@Override
public void onRelease(int primaryCode) {

}
ViduraPrasangana
  • 858
  • 9
  • 17