Creating custom popup keyboard for alternative keys

1.8k views Asked by At

I'm trying to create a custom popup keyboard for alternative keys in android. By using the default keyboard only customization I can do is to provide a custom layout for pop keyboard.

I need customize the behaviour as well (Like the one in the Gboard) Such as,

(1) when a button is long pressed, by default it should highlight an specific key

(2) Keys can be highlighted and also selected by moving the finger(long press the key and move the finger same time)

These are the links I referenced:

Building a custom android keyboard

Creating a SoftKeyboard with Multiple/Alternate characters per key

How do you disable the SoftKeyboard key preview window?

This is the popup keyboard in Gboard enter image description here

Any suggestions/help would be appreciated.

Thank you.

2

There are 2 answers

1
PRATEEK BHARDWAJ On
    <?xml version="1.0" encoding="utf-8"?>


    <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
        android:keyWidth="10%p"
        android:horizontalGap="0px"
        android:verticalGap="0px"
        android:keyHeight="@dimen/key_height">
        <Row android:keyHeight="2px"></Row>
        <Row>
            <Key
                android:codes="49"
                android:keyEdgeFlags="left"
                android:keyLabel="1" />
            <Key
                android:codes="50"
                android:keyLabel="2" />
            <Key
                android:codes="51"
                android:keyLabel="3" />
            <Key
                android:codes="52"
                android:keyLabel="4" />
            <Key
                android:codes="53"
                android:keyLabel="5" />
            <Key
                android:codes="54"
                android:keyLabel="6" />
            <Key
                android:codes="55"
                android:keyLabel="7" />
            <Key
                android:codes="56"
                android:keyLabel="8" />
            <Key
                android:codes="57"
                android:keyLabel="9" />
            <Key
                android:codes="48"
                android:keyEdgeFlags="right"
                android:keyLabel="0" />
        </Row>

        <Row>
            <Key
                android:codes="113"
                android:keyEdgeFlags="left"
                android:keyLabel="q" />
            <Key
                android:codes="119"
                android:keyLabel="w" />

            <Key
                android:codes="101"
                android:keyLabel="e" />
            <Key
                android:codes="114"
                android:keyLabel="r" />
            <Key
                android:codes="116"
                android:keyLabel="t" />
            <Key
                android:codes="121"
                android:keyLabel="y" />
            <Key
                android:codes="117"
                android:keyLabel="u" />
            <Key
                android:codes="105"
                android:keyLabel="i" />

            <Key
                android:codes="111"
                android:keyLabel="o" />
            <Key
                android:codes="112"
                android:keyEdgeFlags="right"
                android:keyLabel="p" />
        </Row>


        <Row>

            <Key
                android:codes="97" android:keyLabel="a" android:horizontalGap="5%p"
                android:keyEdgeFlags="left" android:popupKeyboard="@xml/keyboard_popup_template"
                android:popupCharacters="áăä"/>
            <Key
                android:codes="115"
                android:keyLabel="s" />
            <Key
                android:codes="100"
                android:keyLabel="d" />
            <Key
                android:codes="102"
                android:keyLabel="f" />
            <Key
                android:codes="103"
                android:keyLabel="g" />
            <Key
                android:codes="104"
                android:keyLabel="h" />
            <Key
                android:codes="106"
                android:keyLabel="j" />
            <Key
                android:codes="107"
                android:keyLabel="k" />
            <Key
                android:codes="108"
                android:keyEdgeFlags="right"
                android:keyLabel="l" />


        </Row>

        <Row>
            <Key
                android:codes="-1" android:keyIcon="@drawable/narrow2"
                android:keyWidth="15%p" android:isModifier="true"
                android:isSticky="true" android:keyEdgeFlags="left" />
            <Key
                android:codes="122"
                android:keyLabel="z"
                android:keyWidth="15%p" />
            <Key
                android:codes="120"
                android:keyLabel="x"
                android:keyWidth="15%p" />
            <Key
                android:codes="99"
                android:keyLabel="c"
                android:keyWidth="15%p" />
            <Key
                android:codes="118"
                android:keyLabel="v"
                android:keyWidth="15%p" />
            <Key
                android:codes="98"
                android:keyLabel="b"
                android:keyWidth="15%p" />
            <Key
                android:codes="110"
                android:keyLabel="n"
                android:keyWidth="15%p" />
            <Key
                android:codes="109"
                android:keyLabel="m"
                android:keyWidth="15%p" />
            <Key
                android:codes="-5"
                android:isRepeatable="true"
                android:keyEdgeFlags="right"
                android:keyIcon="@drawable/sym_keyboard_delete"
                android:keyWidth="20%p" />
        </Row>

        <Row
            android:rowEdgeFlags="bottom"
            android:verticalGap="5px">

            <Key
                android:codes="-2"
                android:keyEdgeFlags="left"
                android:keyLabel="123"
                android:keyWidth="15%p" />
            <Key
                android:codes="64"
                android:keyLabel="\@"
                android:keyWidth="10%p" />

            <Key
                android:codes="-101"
                android:keyIcon="@drawable/sym_keyboard_language_switch"
                android:keyWidth="10%p" />
            <Key
                android:codes="32"
                android:isRepeatable="true"
                android:keyLabel="SPACE"
                android:keyWidth="30%p" />

            <Key
                android:codes="46"
                android:keyLabel="."
                android:keyWidth="10%p" />
            <Key
                android:codes="44"
                android:keyLabel=","
                android:keyWidth="10%p"
                android:popupCharacters=".,?!#@"
                android:popupKeyboard="@xml/keyboard_popup_template" />
            <Key
                android:codes="-4"
                android:keyEdgeFlags="right"
                android:keyLabel="DONE"
                android:keyWidth="20%p" />
        </Row>

        <Row android:keyHeight="2px"></Row>

    </Keyboard>

Please try it.
0
mortalis On

As I see, you've already checked this article:
https://www.blackcj.com/blog/2016/03/30/building-a-custom-android-keyboard

It explains how to add a custom layout for the popup keyboard.
The only customization it allows is changing keys background and text color.

Also, you could use a KeyboardView subclass and then override its methods to achieve you goals, like onTouchEvent() to capture motion events or onDraw() to repaint keyboard regions:

<org.home.CustomPopupKeyboard
  android:id="@android:id/keyboardView"
  ...
/>

Also, check the Hacker's Keyboard source:
https://github.com/klausw/hackerskeyboard

Seems, it uses the LatinKeyboardBaseView extends View class for the popup keyboard, in the layout/keyboard_popup.xml.


EDIT:

According to the Hacker's Keyboard code, the only way I found to close the popup when a key is released is creating your own KeyboardView class, which extends the View directly, and then changing its onTouchEvent().

The Android's native KeyboardView class has PopupWindow mPopupKeyboard property which is private so you can't subclass it and call mPopupKeyboard.dismiss() to hide the popup.

The chain that goes from releasing a key to the popup closing is:

  • LatinKeyboardBaseView::onTouchEvent() > case MotionEvent.ACTION_UP: onUpEvent() > tracker.onUpEvent()
  • PointerTracker::onUpEvent() > detectAndSendKey() > listener.onCancel()
  • LatinKeyboardBaseView::onCancel() (implementation of the OnKeyboardActionListener interface) > dismissPopupKeyboard() > mMiniKeyboardPopup.dismiss()