Создание SoftKeyboard с несколькими / альтернативными символами на клавишу - PullRequest
43 голосов
/ 13 октября 2011

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

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

enter image description here

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

enter image description here

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

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

Редактировать: Помогло бы, если бы ссылка developer.android.com на клавиатуру LatinIME не ссылалась на изображение Овцы :) Фактический исходный код для LatinIME.java .

Редактировать 2: В качестве ссылки больше, чем что-либо еще, я полагаю, что это последовательность действий, которую выполняет обычное действие longPress для отображения всплывающей клавиатуры в KeyboardView.java :

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

Редактировать 3:

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

enter image description here

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

Редактировать 4: Перемещенная клавиша Предварительный просмотр вопроса здесь, поскольку он немного не по теме:

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

Ответы [ 6 ]

51 голосов
/ 13 октября 2011

Реализация всплывающего окна с альтернативной клавишей:

Для каждой клавиши, для которой вы хотите иметь всплывающую клавиатуру, вы должны определить 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: layout / 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

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

14 голосов
/ 14 октября 2011

Судя по собственной попытке кодирования программной клавиатуры, я обнаружил, что:

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

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

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

Теперь о том, что вы можете делать:

  • Вы можете обойти эту проблему, предоставив картинки для ключей: используйте 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:

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

выдаст 97 = 'a' для одного касания, 224 = 'à' для двойного касания и 230 = 'æ' для тройного касания.

Длительность рассмотрения двойного касания в исходном коде Android установлена ​​на 800 мс. Это, к сожалению, жестко закодировано (и я чувствую себя немного высоко).

Имейте в виду, что при двойном касании он в основном отправляет сначала «a», а затем при втором нажатии посылает «à». Некоторым приложениям это не понравится.

12 голосов
/ 21 сентября 2013

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

@Override
protected boolean onLongPress(Key key) {
    if (key.codes[0] == '1') {
        getOnKeyboardActionListener().onKey('!', null);
        return true;
    }
}
7 голосов
/ 12 марта 2016

Если вы хотите, чтобы над клавишей был текст, вы можете сделать это с помощью метода 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
            {}
        }
    }
}
5 голосов
/ 24 сентября 2016

Для тех, кто пытается отклонить всплывающую клавиатуру, нажав за пределами ее области просмотра, мне посчастливилось поместить TouchListener в KeyboardView внутри класса, расширяющего 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 ...
}
0 голосов
/ 23 февраля 2018

если вы хотите, чтобы над клавишей был текст, вы можете сделать это с помощью метода 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;
...