Создание SoftKeyboard с несколькими / альтернативными символами на ключ

я следовал примеры на developer.android.com о Методы Ввода и SoftKeyboard примера приложения. Вместе они дают более чем достаточно информации о создании простой клавиатуры.

то, что я не вижу в API, - это возможность создавать альтернативные / несколько символов на ключ, который доступен на стандартной клавиатуре (LatinIME Клавиатура.)

enter image description here

вышеуказанное изображение является результатом длительного нажатия на клавишу" a". Когда вы долго нажимаете клавишу, можно заполнить всплывающее окно альтернативными символами.

enter image description here

также можно дать всплывающее подсказку на некоторых клавишах, которая предложит пользователю нажать и удерживать клавишу, чтобы получить всплывающее меню.

до сих пор я не нашел ни одного источника информации о том, как это достигается, надеюсь кто-то сможет дать мне фору, а до тех пор я буду следовать исходному коду встроенной клавиатуры и посмотреть, смогу ли я его перепроектировать.

Edit: поможет, если developer.android.com Ссылка на клавиатуру LatinIME не ссылалась на изображение овцы :) фактический исходный код LatinIME.java.

Edit 2: больше как ссылка, чем что-либо еще, это последовательность I поверьте, обычное действие longPress проходит, чтобы показать всплывающую клавиатуру в KeyboardView.java:

onTouchEvent()
onModifiedTouchEvent()
mHandkler.handleMessage() with MSG_LONGPRESS
openPopupIfRequired() 
onLongPress()

Edit 3:

Я все еще не понял этого - как вы добавляете предложения ярлыка к ключам? Ответ предполагает, что он не встроен в API, и действительно, я не нашел код для этого. Однако клавиатура на 2.3.4 (API 10) показывает, что эта функция реализовано:

enter image description here

очень хотелось бы выяснить, как он это делает, но его нет нигде в onDraw() метод, который я вижу , что заставляет меня поверить, что он написан вне элемента KeyboardView. Однако я не могу найти layout файл, используемый для отображения элемента KeyboardView на встроенной клавиатуре - если кто-нибудь знает, где это найти, возможно, это даст мне ключ, который мне нужен.

Edit 4: предварительный просмотр перемещенной клавиши вопрос вот как это немного не по теме:

Как отключить окно предварительного просмотра ключа SoftKeyboard?

6 ответов


реализация альтернативного ключа popup:

для каждой клавиши, которую вы хотите иметь всплывающую клавиатуру, вы должны определить popupCharacters и popupKeyboard:

/res/xml/[Keyboard].xml

<Key android:keyLabel="("
    android:popupKeyboard="@xml/keyboard_popup_template"
    android:popupCharacters="[{&lt;" />

на popupKeyboard представляет собой XML-представление клавиатуры, используемой во всплывающем окне, содержащем альтернативные клавиши:

/res/xml/keyboard_popup_template.xml

<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="10%p"
    android:horizontalGap="0px"
    android:verticalGap="0px"
    android:keyHeight="56dp">
</Keyboard>

укладка альтернативного ключа всплывающее окно:

если вы хотите изменить макет/стиль всплывающего окна (по умолчанию @android: макет / keyboard_popup_keyboard.в XML) можно указать android:popupLayout атрибут, который указывает на файл макета:

<android.inputmethodservice.KeyboardView
    android:id="@+id/keyboard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="#FF272727"
    android:popupLayout="@layout/keyboard_popup_keyboard" />

Реализация Наложения Предварительного Просмотра Ключа:

единственное решение, которое я смог собрать, чтобы показать предварительный просмотр ключей (без полной перезаписи исходного кода KeyboardView) , ниже:

упаковка <KeyboardView> тег <FrameLayout> С высоты умножением keyHeight по количеству строк. Внутри этого тега я просто создал LinearLayout для хранения строк, а затем LinearLayout для каждой строки, содержащей TextView с весом, равным значению %p, указанному для каждого <Key>:

<TextView android:text="!" style="@style/Custom.Widget.KeyboardKeyOverlay"  android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="10"/>

и стиле:

<style name="CustomTheme.Widget.KeyboardKeyOverlay">
    <item name="android:background">@android:color/transparent</item>
    <item name="android:textColor">#FFAAAAAA</item>
    <item name="android:paddingRight">6dp</item>
    <item name="android:paddingTop">4dp</item>
    <item name="android:textSize">10sp</item>
    <item name="android:gravity">right</item>
    <item name="android:textStyle">bold</item>
</style>         

который производит это:

enter image description here

я не буду счастлив, пока я удалось реализовать это так же, как и системная клавиатура!


судя по моей попытке кодирования softkeyboard я узнал, что:

  • Nice / bling особенности обычно требует, чтобы вы расширить KeyboardView и в основном писать большие части кода чертежа. К сожалению, вы не может сделайте это, переопределив некоторые ключевые методы, так как почти все является частным. Возможно, вы захотите взглянуть (и позаимствовать код у:
    • (base)/core/java/android/inputmethodservice/KeyboardView.java (РЕПО кода ядра андроида)
    • (apps)/other/LatinIME/LatinKeyboardView.java (ядро android apps repo)

обратите внимание, что овцы на android.kernel.org есть ли сказать вам, что РЕПО закрыто из-за крекеров, но есть зеркала кода в другом месте (к сожалению, потеряли ссылки)

  • базовый KeyboardView и нет поддержка теневых ключевых подсказок, вы должны закодировать свой собственный KeyboardView, чтобы получить возможность переопределить метод onDraw ().

теперь о том, что вы can do:

  • вы можете обойти эту проблему, предоставив изображения для ключей: используйте xml <Key ... android:keyIcon="@drawable/this_key_icon_file /> для этого. К сожалению, у вас наверняка будут плохие результаты для писем с этим методом (проблемы с разрешением).

  • вы можете использовать (и настроить внешний вид) всплывающей клавиатуры, которая появляется при длительном нажатии.

объявить шаблон клавиатуры res/xml/kbd_popup_template.xml :

<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">
</Keyboard>

объявить строковые значения, содержащие нужные клавиши на этой клавиатуре res/values/strings.xml:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string name="alternates_for_a">àáâãäåæ</string>
</ressources>

затем используйте оба в определении раскладки клавиатуры:

<Key android:codes="97" android:keyLabel="a"  
    android:popupKeyboard="@xml/kbd_popup_template"
    android:popupCharacters="@string/alternates_for_a" />
  • вы также можете использовать двойной кран, тройной кран, ... функция для создания альтернатив для ключа, который вы нажимаете. Для этого просто используйте список для Android keycodes:

    <Key android:codes="97,224,230" .../>

будет производить 97='a' для одного крана, 224='à ' для двойного нажатия и 230='æ' для тройной кран.

продолжительность рассмотрения двойного нажатия установлена на 800 мс в исходном коде android. К сожалению, он жестко закодирован (и немного высок, я чувствую).

имейте в виду, что при двойном нажатии он в основном отправляет"a 'во-первых, затем, на второй кран он отправляет'à'. Некоторым приложениям это не понравится.


эта всплывающая клавиатура с кнопкой закрытия раздражает, когда у нас есть только один всплывающий символ. Более простой способ-переопределить метод onLongPress класса KeyboardView.

@Override
protected boolean onLongPress(Key key) {
    if (key.codes[0] == '1') {
        getOnKeyboardActionListener().onKey('!', null);
        return true;
    }
}

Если вы хотите иметь текст поверх своего ключа, вы можете сделать это в методе onDraw () в своем классе, который переопределяет KeyboardView

 @Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    ...
    Paint paint = new Paint();
    paint.setTextAlign(Paint.Align.CENTER);
    paint.setTextSize(18);
    paint.setColor(Color.WHITE);
    //get all your keys and draw whatever you want
    List <Keyboard.Key> keys = getKeyboard().getKeys();
    for(Keyboard.Key key: keys) {
        if(key.label != null) {

            if (key.label.toString().equals("q") || key.label.toString().equals("Q"))
                canvas.drawText(String.valueOf(1), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("w") || key.label.toString().equals("W"))
                canvas.drawText(String.valueOf(2), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("e") || key.label.toString().equals("E"))
                canvas.drawText(String.valueOf(3), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("r") || key.label.toString().equals("R"))
                canvas.drawText(String.valueOf(4), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("t") || key.label.toString().equals("T"))
                canvas.drawText(String.valueOf(5), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("y") || key.label.toString().equals("Y"))
                canvas.drawText(String.valueOf(6), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("u") || key.label.toString().equals("U"))
                canvas.drawText(String.valueOf(7), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("i") || key.label.toString().equals("I"))
                canvas.drawText(String.valueOf(8), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("o") || key.label.toString().equals("o"))
                canvas.drawText(String.valueOf(9), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else if (key.label.toString().equals("p") || key.label.toString().equals("P"))
                canvas.drawText(String.valueOf(0), key.x + (key.width / 2) + 10, key.y + 25, paint);

            else
            {}
        }
    }
}

для тех, кто пытается отклонить всплывающую клавиатуру, нажав за пределами ее области просмотра, мне повезло поставить TouchListener на KeyboardView внутри класса extending InputMethodService

public class YourIME extends InputMethodService{
    @Override 
    public View onCreateInputView() {
        mInputView = (LatinKeyboardView) getLayoutInflater().inflate(R.layout.input, null);
        setLatinKeyboard(mQwertyKeyboard);

        mInputView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {

                if(motionEvent.getAction() == MotionEvent.ACTION_DOWN) {                        
                    mInputView.closing(); // Close popup keyboard if it's showing
                }
                return false;
            }
        });

        return mInputView;
    }
// The rest of your ime ...
}

Если вы хотите иметь текст поверх вашего ключа, вы можете сделать это в методе onDraw () в своем классе, который расширяет KeyboardView я сделал что-то вроде этого, возможно, это может помочь кому-то

enter image description here

 @Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Log.d("LatinKeyboardView", "onDraw");

    Paint paint = new Paint();
    paint.setTextAlign(Paint.Align.CENTER);
    paint.setTextSize(30);
    paint.setColor(Color.LTGRAY);

    List<Key> keys = getKeyboard().getKeys();
    for (Key key : keys) {
        if (key.label != null) {
            switch (key.codes[0]) {

                //qQ
                case 81:
                case 113:
                case 1602:
                case 1618:
                    canvas.drawText(String.valueOf(1), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //wW
                case 87:
                case 119:
                case 1608:
                case 1572:
                    canvas.drawText(String.valueOf(2), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //eE
                case 69:
                case 101:
                case 1593:
                case 1617:
                    canvas.drawText(String.valueOf(3), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;


                //rR
                case 82:
                case 114:
                case 1585:
                case 1681:
                    canvas.drawText(String.valueOf(4), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //tT
                case 84:
                case 116:
                case 1578:
                case 1657:
                    canvas.drawText(String.valueOf(5), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //yY
                case 89:
                case 121:
                case 1746:
                case 1552:
                    canvas.drawText(String.valueOf(6), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //uU
                case 85:
                case 117:
                case 1569:
                case 1574:
                    canvas.drawText(String.valueOf(7), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //iI
                case 73:
                case 105:
                case 1740:
                case 1648:
                    canvas.drawText(String.valueOf(8), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //oO
                case 79:
                case 111:
                case 1729:
                case 1731:
                    canvas.drawText(String.valueOf(9), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //pP
                case 80:
                case 112:
                case 1662:
                case 1615:
                    canvas.drawText(String.valueOf(0), key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;


                //aA
                case 65:
                case 97:
                case 1575:
                case 1570:
                    canvas.drawText("@", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //sS
                case 83:
                case 115:
                case 1587:
                case 1589:
                    canvas.drawText("#", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //dD
                case 68:
                case 100:
                case 1583:
                case 1672:
                    canvas.drawText("$", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //fF
                case 70:
                case 102:
                case 1601:
                case 1613:
                    canvas.drawText("%", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //gG
                case 71:
                case 103:
                case 1711:
                case 1594:
                    canvas.drawText("&", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //hH
                case 72:
                case 104:
                case 1726:
                case 1581:
                    canvas.drawText("-", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //jJ
                case 74:
                case 106:
                case 1580:
                case 1590:
                    canvas.drawText("+", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //kK
                case 75:
                case 107:
                case 1705:
                case 1582:
                    canvas.drawText("(", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //lL
                case 76:
                case 108:
                case 1604:
                case 1614:
                    canvas.drawText(")", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //zZ
                case 90:
                case 122:
                case 1586:
                case 1584:
                    canvas.drawText("*", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //xX
                case 88:
                case 120:
                case 1588:
                case 1679:
                    canvas.drawText("\"", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //cC
                case 67:
                case 99:
                case 1670:
                case 1579:
                    canvas.drawText("\'", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //vV
                case 86:
                case 118:
                case 1591:
                case 1592:
                    canvas.drawText(":", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //bB
                case 66:
                case 98:
                case 1576:
                case 1616:
                    canvas.drawText(";", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;

                //nN
                case 78:
                case 110:
                case 1606:
                case 1722:
                    canvas.drawText("!", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;
                //mM
                case 77:
                case 109:
                case 1605:
                case 1611:
                    canvas.drawText("?", key.x + (key.width - keyXAxis), key.y + keyYAxis, paint);
                    break;


            }

        }

    }
}

отрегулируйте эти оси в соответствии с вашим выбором

int keyXAxis = 25;
int keyYAxis = 50;