Как сделать в Android собственную клавиатуру?

106

Я хочу сделать кастомную клавиатуру. Я не знаю, как это сделать с помощью XML и Java. На следующем рисунке показана модель клавиатуры, которую я хочу сделать. Нужны только числа.

введите описание изображения здесь

XX_брат
источник
6
[Создайте свою собственную клавиатуру с использованием XML-макетов для устройств Android] ( tutorials-android.blogspot.com/2011/06/… )
Jorgesys
1
На
Tuts
У Google есть образец проекта "SoftKeyboard", или здесь есть ссылки на довольно много ресурсов: customkeyboarddetails.blogspot.com/2019/02/…
oliversisson

Ответы:

83

Прежде всего вам понадобится keyboard.xmlфайл, который будет помещен в res/xmlпапку (если папка не существует, создайте ее).

<?xml version="1.0" encoding="utf-8"?> 
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="15%p"
    android:keyHeight="15%p" >

    <Row>
        <Key android:codes="1"    android:keyLabel="1" android:horizontalGap="4%p"/>
        <Key android:codes="2"    android:keyLabel="2" android:horizontalGap="4%p"/>
        <Key android:codes="3"    android:keyLabel="3" android:horizontalGap="4%p" />
        <Key android:codes="4"    android:keyLabel="4" android:horizontalGap="4%p" />
        <Key android:codes="5"    android:keyLabel="5" android:horizontalGap="4%p" />
    </Row>
    <Row>
        <Key android:codes="6"    android:keyLabel="6" android:horizontalGap="4%p"/>
        <Key android:codes="7"    android:keyLabel="7" android:horizontalGap="4%p"/>
        <Key android:codes="8"    android:keyLabel="8" android:horizontalGap="4%p" />
        <Key android:codes="9"    android:keyLabel="9" android:horizontalGap="4%p" />
        <Key android:codes="0"    android:keyLabel="0" android:horizontalGap="4%p" />
    </Row>

    <Row>
        <Key android:codes="-1"    android:keyIcon="@drawable/backspace" android:keyWidth="34%p" android:horizontalGap="4%p"/>
        <Key android:codes="100"    android:keyLabel="Enter" android:keyWidth="53%p" android:horizontalGap="4%p"/>
    </Row>
 </Keyboard>

** Обратите внимание, что вам нужно будет создать backspaceчертеж и поместить его в папку res / drawable-ldpi с очень маленьким размером (например, 18x18 пикселей)

Затем в XML-файл, который вы хотите использовать (где находится ваш TextView), вы должны добавить следующий код:

<RelativeLayout
 ...
>

        .....


        <android.inputmethodservice.KeyboardView
             android:id="@+id/keyboardview"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:layout_alignParentBottom="true"
             android:layout_centerHorizontal="true"
             android:focusable="true"
             android:focusableInTouchMode="true"
             android:visibility="gone" 
         />
         
        ......


</RelativeLayout>

** Обратите внимание, что файл xml, в который вы поместите android.inputmethodservice.KeyboardView, должен быть RelativeLayout, чтобы можно было установить alignParentBottom="true"(обычно клавиатуры представлены в нижней части экрана)

Затем вам нужно добавить следующий код в onCreateфункцию, Activityкоторая обрабатывает TextViewклавиатуру, к которой вы хотите прикрепить

    // Create the Keyboard
    mKeyboard= new Keyboard(this,R.xml.keyboard);

    // Lookup the KeyboardView
    mKeyboardView= (KeyboardView)findViewById(R.id.keyboardview);
    // Attach the keyboard to the view
    mKeyboardView.setKeyboard( mKeyboard );
    
    // Do not show the preview balloons
    //mKeyboardView.setPreviewEnabled(false);
    
    // Install the key handler
    mKeyboardView.setOnKeyboardActionListener(mOnKeyboardActionListener);

** Обратите внимание, что mKeyboardи mKeyboardViewявляются переменными частного класса, которые вам необходимо создать.

Затем вам понадобится следующая функция для открытия клавиатуры (вы должны связать ее с TextView через onClickсвойство xml)

    public void openKeyboard(View v)
    {
       mKeyboardView.setVisibility(View.VISIBLE);
       mKeyboardView.setEnabled(true);
       if( v!=null)((InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), 0);
    }

И, наконец, вам понадобится то, OnKeyboardActionListenerчто будет обрабатывать ваши события

private OnKeyboardActionListener mOnKeyboardActionListener = new OnKeyboardActionListener() {
    @Override public void onKey(int primaryCode, int[] keyCodes) 
    {
         //Here check the primaryCode to see which key is pressed 
         //based on the android:codes property
         if(primaryCode==1)
         {
            Log.i("Key","You just pressed 1 button");
         }
    }

    @Override public void onPress(int arg0) {
    }

    @Override public void onRelease(int primaryCode) {
    }

    @Override public void onText(CharSequence text) {
    }

    @Override public void swipeDown() {
    }

    @Override public void swipeLeft() {
    }

    @Override public void swipeRight() {
    }

    @Override public void swipeUp() {
    }
};

Надеюсь, это поможет!!!

Большая часть кода найдена здесь

____________________________________________________________-

РЕДАКТИРОВАТЬ:

Поскольку KeyboardView является устаревшим с уровня API 29, вы можете найти его код на этом веб-сайте и создать класс в своем коде перед реализацией клавиатуры, как описано выше.

Понтиос
источник
1
Что, если я не хочу, чтобы клавиатура располагалась внизу экрана? (например, я хочу, чтобы пользователь мог его перетаскивать). Могу ли я управлять этим через приложение для клавиатуры или это обрабатывается системой Android?
user3294126 02
ширина клавиатуры не заполняет экран, что мне делать, чтобы она заполняла все экраны
Джордж Томас,
в каком родительском макете находится KeyboardView? Также вы проверили layout_width в KeyboardView ??
Понтиос,
1
Имейте в виду, что классы KeyboardView и Keyboard не рекомендуются Google с уровня API 29. Таким образом, это решение больше не будет работать в будущем, если вам потребуется настроить таргетинг на новый уровень API.
maex
2
keyboardView устарел Google. какое новое решение?
tohidmahmoudvand
79

Системная клавиатура

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

Пример ниже будет выглядеть так. Вы можете изменить его для любой раскладки клавиатуры.

введите описание изображения здесь

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

1. Начните новый проект Android.

Я назвал свой проект «Custom Keyboard». Называйте это как хотите. Больше здесь ничего особенного нет. Я просто оставлю MainActivityи «Привет, мир!» макет как есть.

2. Добавьте файлы макета

Добавьте следующие два файла в res/layoutпапку вашего приложения :

  • keyboard_view.xml
  • key_preview.xml

keyboard_view.xml

Это представление похоже на контейнер, в котором будет находиться наша клавиатура. В этом примере есть только одна клавиатура, но вы можете добавить другие клавиатуры и менять их местами KeyboardView.

<?xml version="1.0" encoding="utf-8"?>
<android.inputmethodservice.KeyboardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyboard_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:keyPreviewLayout="@layout/key_preview"
    android:layout_alignParentBottom="true">

</android.inputmethodservice.KeyboardView>

key_preview.xml

Предварительный просмотр клавиш - это раскладка, которая появляется при нажатии клавиши клавиатуры. Он просто показывает, какую клавишу вы нажимаете (на случай, если ваши большие толстые пальцы закрывают ее). Это не всплывающее окно с множественным выбором. Для этого вам следует проверить представление « Кандидаты» .

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="@android:color/white"
    android:textColor="@android:color/black"
    android:textSize="30sp">
</TextView>

3. Добавьте вспомогательные файлы xml.

Создайте xmlпапку в своей resпапке. (Щелкните правой кнопкой мыши resи выберите « Создать»> «Каталог» .)

Затем добавьте к нему следующие два файла xml. (Щелкните xmlпапку правой кнопкой мыши и выберите « Создать»> «Файл ресурсов XML» .)

  • number_pad.xml
  • method.xml

number_pad.xml

Здесь начинается интереснее. Это Keyboardопределяет расположение клавиш .

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="20%p"
    android:horizontalGap="5dp"
    android:verticalGap="5dp"
    android:keyHeight="60dp">

    <Row>
        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
        <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" android:keyEdgeFlags="right"/>
    </Row>

    <Row>
        <Key android:codes="54" android:keyLabel="6" android:keyEdgeFlags="left"/>
        <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:keyLabel="0" android:keyEdgeFlags="right"/>
    </Row>

    <Row>
        <Key android:codes="-5"
             android:keyLabel="DELETE"
             android:keyWidth="40%p"
             android:keyEdgeFlags="left"
             android:isRepeatable="true"/>
        <Key android:codes="10"
             android:keyLabel="ENTER"
             android:keyWidth="60%p"
             android:keyEdgeFlags="right"/>
    </Row>

</Keyboard>

Вот некоторые моменты, на которые следует обратить внимание:

  • keyWidth: Это ширина каждой клавиши по умолчанию. В 20%pозначает , что каждый ключ должен занимать 20% ширины п Arent. Однако его можно переопределить с помощью отдельных клавиш, как вы можете видеть, это произошло с клавишами Delete и Enter в третьей строке.
  • keyHeight: Здесь он жестко запрограммирован, но вы можете использовать что-то вроде @dimen/key_heightдинамической установки для разных размеров экрана.
  • Gap: Горизонтальный и вертикальный промежуток указывает, сколько места нужно оставить между клавишами. Даже если вы установите его 0px, все равно останется небольшой зазор.
  • codes: Это может быть значение Unicode или пользовательского кода, определяющее, что происходит или что вводится при нажатии клавиши. Посмотрите keyOutputText, хотите ли вы ввести более длинную строку Unicode.
  • keyLabel: Это текст, который отображается на клавише.
  • keyEdgeFlags: Указывает, по какому краю должен быть выровнен ключ.
  • isRepeatable: Если вы удерживаете кнопку, ввод будет повторяться.

method.xml

Этот файл сообщает системе о доступных подтипах методов ввода. Я просто включаю сюда минимальную версию.

<?xml version="1.0" encoding="utf-8"?>
<input-method
    xmlns:android="http://schemas.android.com/apk/res/android">

    <subtype
        android:imeSubtypeMode="keyboard"/>

</input-method>

4. Добавьте код Java для обработки ввода с клавиатуры.

Создайте новый файл Java. Назовем это MyInputMethodService. Этот файл связывает все воедино. Он обрабатывает ввод, полученный с клавиатуры, и отправляет его любому представлению, которое его получает ( EditTextнапример).

public class MyInputMethodService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {

    @Override
    public View onCreateInputView() {
        // get the KeyboardView and add our Keyboard layout to it
        KeyboardView keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard_view, null);
        Keyboard keyboard = new Keyboard(this, R.xml.number_pad);
        keyboardView.setKeyboard(keyboard);
        keyboardView.setOnKeyboardActionListener(this);
        return keyboardView;
    }

    @Override
    public void onKey(int primaryCode, int[] keyCodes) {

        InputConnection ic = getCurrentInputConnection();
        if (ic == null) return;
        switch (primaryCode) {
            case Keyboard.KEYCODE_DELETE:
                CharSequence selectedText = ic.getSelectedText(0);
                if (TextUtils.isEmpty(selectedText)) {
                    // no selection, so delete previous character
                    ic.deleteSurroundingText(1, 0);
                } else {
                    // delete the selection
                    ic.commitText("", 1);
                }
                break;
            default:
                char code = (char) primaryCode;
                ic.commitText(String.valueOf(code), 1);
        }
    }

    @Override
    public void onPress(int primaryCode) { }

    @Override
    public void onRelease(int primaryCode) { }

    @Override
    public void onText(CharSequence text) { }

    @Override
    public void swipeLeft() { }

    @Override
    public void swipeRight() { }

    @Override
    public void swipeDown() { }

    @Override
    public void swipeUp() { }
}

Ноты:

  • В OnKeyboardActionListener прослушивает ввода с клавиатуры. Также требуются все эти пустые методы в этом примере.
  • Это InputConnectionто, что используется для отправки ввода в другое представление, например EditText.

5. Обновите манифест.

Я поставил это последнее, а не первое, потому что оно относится к файлам, которые мы уже добавили выше. Чтобы зарегистрировать настраиваемую клавиатуру в качестве системной, вам необходимо добавить serviceраздел в файл AndroidManifest.xml . Поместите в applicationраздел после activity.

<manifest ...>
    <application ... >
        <activity ... >
            ...
        </activity>

        <service
            android:name=".MyInputMethodService"
            android:label="Keyboard Display Name"
            android:permission="android.permission.BIND_INPUT_METHOD">
            <intent-filter>
                <action android:name="android.view.InputMethod"/>
            </intent-filter>
            <meta-data
                android:name="android.view.im"
                android:resource="@xml/method"/>
        </service>

    </application>
</manifest>

Это оно! Теперь вы можете запустить свое приложение. Однако вы ничего не увидите, пока не включите клавиатуру в настройках.

6. Включите клавиатуру в настройках.

Каждый пользователь, который хочет использовать вашу клавиатуру, должен будет включить ее в настройках Android. Подробные инструкции о том, как это сделать, см. По следующей ссылке:

Вот краткое изложение:

  • Перейдите в «Настройки Android»> «Языки и ввод»> «Текущая клавиатура»> «Выбрать клавиатуру».
  • Вы должны увидеть свою настраиваемую клавиатуру в списке. Включите это.
  • Вернитесь и снова выберите Текущая клавиатура. Вы должны увидеть свою настраиваемую клавиатуру в списке. Выбери это.

Теперь у вас должна быть возможность использовать клавиатуру везде, где вы можете печатать на Android.

Дальнейшее обучение

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

Продолжается

Не нравится, как стандарт KeyboardView выглядит и ведет себя? Я точно не знаю. Похоже, он не обновлялся с Android 2.0. Как насчет всех этих настраиваемых клавиатур в Play Store? Они не похожи на уродливую клавиатуру выше.

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

  1. Создайте собственное пользовательское представление клавиатуры, которое подклассы ViewGroup. Вы можете заполнить его Buttons или даже создать свои собственные представления ключей для этого подкласса View. Если вы используете всплывающие окна, обратите внимание на это .
  2. Добавьте на клавиатуру настраиваемый интерфейс прослушивателя событий . Вызывайте его методы для таких вещей, как onKeyClicked(String text)или onBackspace().
  3. Вам не нужно добавить keyboard_view.xml, key_preview.xmlили number_pad.xmlописанные в направлениях выше , так как это все для стандарта KeyboardView. Вы будете обрабатывать все эти аспекты пользовательского интерфейса в своем пользовательском представлении.
  4. В своем MyInputMethodServiceклассе реализуйте настраиваемый прослушиватель клавиатуры, который вы определили в своем классе клавиатуры. Это вместо того KeyboardView.OnKeyboardActionListener, что больше не нужно.
  5. В методе вашего MyInputMethodServiceкласса onCreateInputView()создайте и верните экземпляр своей настраиваемой клавиатуры. Не забудьте установить для клавиатуры собственный слушатель this.
Suragch
источник
36

Клавиатура в приложении

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

Пример будет выглядеть так. Вы можете изменить его для любой раскладки клавиатуры.

введите описание изображения здесь

1. Начните новый проект Android.

Я назвал свой проект InAppKeyboard. Называйте себя как хотите.

2. Добавьте файлы макета

Раскладка клавиатуры

Добавьте файл макета в res/layoutпапку. Я позвонил в свой keyboard. Клавиатура будет настраиваемым составным представлением, которое мы раздуваем из этого файла макета xml. Вы можете использовать любую раскладку для расположения клавиш, но я использую LinearLayout. Обратите внимание на mergeтеги.

res / layout / keyboard.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/button_1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="1"/>

            <Button
                android:id="@+id/button_2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="2"/>

            <Button
                android:id="@+id/button_3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="3"/>

            <Button
                android:id="@+id/button_4"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="4"/>

            <Button
                android:id="@+id/button_5"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="5"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/button_6"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="6"/>

            <Button
                android:id="@+id/button_7"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="7"/>

            <Button
                android:id="@+id/button_8"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="8"/>

            <Button
                android:id="@+id/button_9"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="9"/>

            <Button
                android:id="@+id/button_0"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="0"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <Button
                android:id="@+id/button_delete"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="Delete"/>

            <Button
                android:id="@+id/button_enter"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:text="Enter"/>

        </LinearLayout>
    </LinearLayout>

</merge>

Макет деятельности

В демонстрационных целях у нашей активности есть сингл, EditTextа клавиатура находится внизу. Я назвал свое собственное представление клавиатуры MyKeyboard. (Мы скоро добавим этот код, поэтому пока не обращайте внимания на ошибку.) Преимущество помещения всего нашего кода клавиатуры в одно представление состоит в том, что это упрощает повторное использование в другом действии или приложении.

res / layout / activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.inappkeyboard.MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#c9c9f1"
        android:layout_margin="50dp"
        android:padding="5dp"
        android:layout_alignParentTop="true"/>

    <com.example.inappkeyboard.MyKeyboard
        android:id="@+id/keyboard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_alignParentBottom="true"/>

</RelativeLayout>

3. Добавьте файл Java для клавиатуры.

Добавьте новый файл Java. Я позвонил в свой MyKeyboard.

Самое важное, что здесь следует отметить, это отсутствие жесткой ссылки ни на один из файлов EditTextили Activity. Это позволяет легко подключить его к любому приложению или действию, которое в нем нуждается. Это настраиваемое представление клавиатуры также использует расширение InputConnection, которое имитирует способ взаимодействия системной клавиатуры с файлом EditText. Вот как мы избегаем жестких ссылок.

MyKeyboard представляет собой составное представление, которое расширяет макет представления, который мы определили выше.

MyKeyboard.java

public class MyKeyboard extends LinearLayout implements View.OnClickListener {

    // constructors
    public MyKeyboard(Context context) {
        this(context, null, 0);
    }

    public MyKeyboard(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyKeyboard(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    // keyboard keys (buttons)
    private Button mButton1;
    private Button mButton2;
    private Button mButton3;
    private Button mButton4;
    private Button mButton5;
    private Button mButton6;
    private Button mButton7;
    private Button mButton8;
    private Button mButton9;
    private Button mButton0;
    private Button mButtonDelete;
    private Button mButtonEnter;

    // This will map the button resource id to the String value that we want to 
    // input when that button is clicked.
    SparseArray<String> keyValues = new SparseArray<>();

    // Our communication link to the EditText
    InputConnection inputConnection;

    private void init(Context context, AttributeSet attrs) {

        // initialize buttons
        LayoutInflater.from(context).inflate(R.layout.keyboard, this, true);
        mButton1 = (Button) findViewById(R.id.button_1);
        mButton2 = (Button) findViewById(R.id.button_2);
        mButton3 = (Button) findViewById(R.id.button_3);
        mButton4 = (Button) findViewById(R.id.button_4);
        mButton5 = (Button) findViewById(R.id.button_5);
        mButton6 = (Button) findViewById(R.id.button_6);
        mButton7 = (Button) findViewById(R.id.button_7);
        mButton8 = (Button) findViewById(R.id.button_8);
        mButton9 = (Button) findViewById(R.id.button_9);
        mButton0 = (Button) findViewById(R.id.button_0);
        mButtonDelete = (Button) findViewById(R.id.button_delete);
        mButtonEnter = (Button) findViewById(R.id.button_enter);

        // set button click listeners
        mButton1.setOnClickListener(this);
        mButton2.setOnClickListener(this);
        mButton3.setOnClickListener(this);
        mButton4.setOnClickListener(this);
        mButton5.setOnClickListener(this);
        mButton6.setOnClickListener(this);
        mButton7.setOnClickListener(this);
        mButton8.setOnClickListener(this);
        mButton9.setOnClickListener(this);
        mButton0.setOnClickListener(this);
        mButtonDelete.setOnClickListener(this);
        mButtonEnter.setOnClickListener(this);

        // map buttons IDs to input strings
        keyValues.put(R.id.button_1, "1");
        keyValues.put(R.id.button_2, "2");
        keyValues.put(R.id.button_3, "3");
        keyValues.put(R.id.button_4, "4");
        keyValues.put(R.id.button_5, "5");
        keyValues.put(R.id.button_6, "6");
        keyValues.put(R.id.button_7, "7");
        keyValues.put(R.id.button_8, "8");
        keyValues.put(R.id.button_9, "9");
        keyValues.put(R.id.button_0, "0");
        keyValues.put(R.id.button_enter, "\n");
    }

    @Override
    public void onClick(View v) {

        // do nothing if the InputConnection has not been set yet
        if (inputConnection == null) return;

        // Delete text or input key value
        // All communication goes through the InputConnection
        if (v.getId() == R.id.button_delete) {
            CharSequence selectedText = inputConnection.getSelectedText(0);
            if (TextUtils.isEmpty(selectedText)) {
                // no selection, so delete previous character
                inputConnection.deleteSurroundingText(1, 0);
            } else {
                // delete the selection
                inputConnection.commitText("", 1);
            }
        } else {
            String value = keyValues.get(v.getId());
            inputConnection.commitText(value, 1);
        }
    }

    // The activity (or some parent or controller) must give us 
    // a reference to the current EditText's InputConnection
    public void setInputConnection(InputConnection ic) {
        this.inputConnection = ic;
    }
}

4. Наведите клавиатуру на EditText.

Для системных клавиатур Android использует InputMethodManager, чтобы указать клавиатуре на выделенный объектEditText . В этом примере действие займет свое место, предоставив ссылку с EditTextнашей настраиваемой клавиатуры на.

Поскольку мы не используем системную клавиатуру, нам нужно отключить ее, чтобы она не появлялась при прикосновении к EditText. Во-вторых, нам нужно получить InputConnectionот EditTextи передать его нашей клавиатуре.

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText editText = (EditText) findViewById(R.id.editText);
        MyKeyboard keyboard = (MyKeyboard) findViewById(R.id.keyboard);

        // prevent system keyboard from appearing when EditText is tapped
        editText.setRawInputType(InputType.TYPE_CLASS_TEXT);
        editText.setTextIsSelectable(true);

        // pass the InputConnection from the EditText to the keyboard
        InputConnection ic = editText.onCreateInputConnection(new EditorInfo());
        keyboard.setInputConnection(ic);
    }
}

Если у вашего Activity есть несколько EditTexts, вам нужно будет написать код для передачи правильного EditText InputConnectionна клавиатуру. (Вы можете сделать это, добавив OnFocusChangeListenerи OnClickListenerв EditTexts. См. Эту статью для обсуждения этого.) Вы также можете скрыть или показать свою клавиатуру в подходящее время.

Законченный

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

Ноты

  • В файле макета xml вы также можете использовать a TextView, Buttonесли хотите, чтобы ключи выглядели лучше. Затем просто сделайте фон доступным для рисования, который изменяет состояние внешнего вида при нажатии.
  • Расширенные настраиваемые клавиатуры: для большей гибкости во внешнем виде клавиатуры и переключении клавиатуры я сейчас создаю настраиваемые представления клавиш, которые являются подклассами, Viewи настраиваемые клавиатуры, которые образуют подкласс ViewGroup. Клавиатура программно раскладывает все клавиши. Клавиши используют интерфейс для связи с клавиатурой (аналогично тому, как фрагменты взаимодействуют с действием). В этом нет необходимости, если вам нужна только одна раскладка клавиатуры, поскольку раскладка xml отлично подходит для этого. Но если вы хотите , чтобы увидеть пример того , что я работаю, проверить все Key*и Keyboard*классы здесь . Обратите внимание, что я также использую там контейнерное представление, функция которого состоит в том, чтобы менять местами клавиатуры.
Suragch
источник
ваш ответ отличный, но как мы можем настроить переключение между оригинальной клавиатурой и этой новой клавиатурой.
Кишан Донга,
@KishanDonga, на клавиатуре можно добавить клавишу для переключения клавиатур. Когда пользователь нажимает на нее, вызовите InputMethodManager#showInputMethodPicker(). Однако, если на исходной клавиатуре нет такой клавиши, единственный способ, которым пользователи могут переключиться на вашу клавиатуру, - это сделать это вручную в системных настройках. Apple превосходит Android в этой области, потому что Apple требует, чтобы на всех клавиатурах была клавиша переключения клавиатуры.
Suragch
@KishanDonga, я только что понял, что это ответ о клавиатуре в приложении, а не о системной клавиатуре. Если вы хотите переключаться между двумя настраиваемыми клавиатурами, вы можете программно переключать их в представление контейнера и из него. Просто добавьте сменную клавиатуру на обе клавиатуры. См. Мое примечание и ссылку "расширенные настраиваемые клавиатуры" в ответе выше.
Suragch
Если вы хотите переключаться между клавиатурой и системной клавиатурой, скройте системную клавиатуру и покажите клавиатуру в нужное время (и наоборот).
Suragch
1
@MarekTakac, вам нужно будет отключить системную клавиатуру и добавлять собственную клавиатуру в каждое действие. Если у действия есть несколько EditTexts, вам нужно будет добавить onFocusChangedListenerк ним, чтобы, когда они получат фокус, вы могли назначить InputConnectionиз текущего EditTextна свою настраиваемую клавиатуру.
Suragch
31

Использование KeyboardView:

KeyboardView kbd = new KeyboardView(context);
kbd.setKeyboard(new Keyboard(this, R.xml.custom));

kbd.setOnKeyboardActionListener(new OnKeyboardActionListener() {
    ....
}

теперь у вас есть kbdнормальный вид.

Самое приятное в этом то, что это R.xml.customотносится к /res/xml/custom.xml, которое определяет в xml раскладку клавиатуры. Дополнительные сведения об этом файле см. Здесь: Keyboard , Keyboard.Row , Keyboard.Key .

большие камни
источник
2
Я использую класс KeyboardView, но с API 29 он устарел.
Абхиджит
14

Вот пример проекта мягкой клавиатуры.

https://developer.android.com/guide/topics/text/creating-input-method.html

Ваши должны быть в тех же строках с другим макетом.

Изменить: если вам нужна клавиатура только в вашем приложении, это очень просто! Создайте линейный макет с вертикальной ориентацией и создайте внутри него 3 линейных макета с горизонтальной ориентацией. Затем поместите кнопки каждой строки в каждый из этих горизонтальных линейных макетов и назначьте кнопкам свойство веса. Используйте android: layout_weight = 1 для всех из них, чтобы они были равномерно распределены.

Это решит. Если вы не получили ожидаемого результата, опубликуйте код здесь, и мы здесь, чтобы помочь вам!

nithinreddy
источник
Редактирование на самом деле плохое, потому что это будет означать, что клавиатура всегда отображается и не будет вести себя как стандартная клавиатура Android.
m0skit0
4

Я недавно наткнулся на этот пост, когда пытался решить, какой метод использовать для создания собственной клавиатуры. Я обнаружил, что API системы Android очень ограничен, поэтому решил создать собственную клавиатуру в приложении. Используя ответ Сурагча в качестве основы для своего исследования, я продолжил разработку собственного компонента клавиатуры . Он размещен на GitHub с лицензией MIT. Надеюсь, это сэкономит кому-то еще много времени и избавит от головной боли.

Архитектура довольно гибкая. Существует одно основное представление (CustomKeyboardView), которое вы можете использовать с любой раскладкой клавиатуры и контроллером, которые вы хотите.

Вам просто нужно объявить CustomKeyboardView в своей активности xml (вы также можете сделать это программно):

    <com.donbrody.customkeyboard.components.keyboard.CustomKeyboardView
    android:id="@+id/customKeyboardView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true" />

Затем зарегистрируйте в нем свой EditText и сообщите ему, какой тип клавиатуры они должны использовать:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val numberField: EditText = findViewById(R.id.testNumberField)
    val numberDecimalField: EditText = findViewById(R.id.testNumberDecimalField)
    val qwertyField: EditText = findViewById(R.id.testQwertyField)

    keyboard = findViewById(R.id.customKeyboardView)
    keyboard.registerEditText(CustomKeyboardView.KeyboardType.NUMBER, numberField)
    keyboard.registerEditText(CustomKeyboardView.KeyboardType.NUMBER_DECIMAL, numberDecimalField)
    keyboard.registerEditText(CustomKeyboardView.KeyboardType.QWERTY, qwertyField)
}

CustomKeyboardView сделает все остальное!

Я отлично разбираюсь в клавиатуре Number, NumberDecimal и QWERTY. Не стесняйтесь загружать его и создавать свои собственные макеты и контроллеры. Выглядит это так:

Android пользовательская клавиатура GIF пейзаж

введите описание изображения здесь

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

Опять же, вот ссылка на проект: Custom In-App Keyboard.

Дон Броди
источник
2

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

Я надеюсь дать лучший ответ, чем Сурагч, улучшив его ответ. Я добавлю все недостающие элементы, которые он не поставил.

Я скомпилировал свой apk с помощью приложения для Android APK Builder 1.1.0. Итак, приступим.

Чтобы создать приложение для Android, нам понадобится пара файлов и папок, которые организованы в определенном формате и написаны с заглавной буквы соответственно.

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

значения -> постоянные данные, такие как colors.xml, strings.xml, styles.xml. Эти файлы должны быть написаны правильно.

drawable -> картинки {jpeg, png, ...}; Назовите их как угодно.

mipmap -> больше фото. используется для значка приложения?

xml -> еще файлы xml.

src -> действует как JavaScript в html. Файлы макета инициируют начальное представление, а ваш файл java будет динамически управлять элементами тега и запускать события. События также могут быть активированы непосредственно в layout.xml, как и в html.

AndroidManifest.xml -> Этот файл регистрирует, о чем ваше приложение. Название приложения, тип программы, необходимые разрешения и т. Д. Это делает Android довольно безопасным. Программы буквально не могут делать то, чего они не просили в Манифесте.

Теперь существует 4 типа программ Android: деятельность, услуга, поставщик контента и приемник вещания. Наша клавиатура будет службой, позволяющей ей работать в фоновом режиме. Его не будет в списке запускаемых приложений; но его можно удалить.

Чтобы скомпилировать ваше приложение, требуется Gradle и подписывание apk. Вы можете изучить его или использовать APK Builder для Android. Это очень просто.

Теперь, когда мы разбираемся в разработке Android, давайте создадим файлы и папки.

  1. Создайте файлы и папки, как я обсуждал выше. Мой каталог будет выглядеть следующим образом:

    • NumPad
      • AndroidManifest.xml
      • src
        • Сарагч
          • num_pad
            • MyInputMethodService.java
      • res
        • выдвижной
          • Suragch_NumPad_icon.png
        • макет
          • key_preview.xml
          • keyboard_view.xml
        • xml
          • method.xml
          • number_pad.xml
        • ценности
          • colors.xml
          • strings.xml
          • styles.xml

Помните, что если вы используете ide, например Android Studio, у него может быть файл проекта.

  1. Напишите файлы.

О: NumPad / res / layout / key_preview.xml

<?xml version="1.0" encoding="utf-8"?>
   <TextView
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:gravity="center"
      android:background="@android:color/white"
      android:textColor="@android:color/black"
      android:textSize="30sp">
</TextView>

B: NumPad / res / layout / keyboard_view.xml

<?xml version="1.0" encoding="utf-8"?>
<android.inputmethodservice.KeyboardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/keyboard_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:keyPreviewLayout="@layout/key_preview"
    android:layout_alignParentBottom="true">

</android.inputmethodservice.KeyboardView>

C: NumPad / res / xml / method.xml

<?xml version="1.0" encoding="utf-8"?>
<input-method  xmlns:android="http://schemas.android.com/apk/res/android">
    <subtype  android:imeSubtypeMode="keyboard"/>
</input-method>

D: Цифровая клавиатура / res / xml / number_pad.xml

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
    android:keyWidth="20%p"
    android:horizontalGap="5dp"
    android:verticalGap="5dp"
    android:keyHeight="60dp">

    <Row>
        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
        <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" android:keyEdgeFlags="right"/>
    </Row>

    <Row>
        <Key android:codes="54" android:keyLabel="6" android:keyEdgeFlags="left"/>
        <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:keyLabel="0" android:keyEdgeFlags="right"/>
    </Row>

    <Row>
        <Key android:codes="-5"
             android:keyLabel="DELETE"
             android:keyWidth="40%p"
             android:keyEdgeFlags="left"
             android:isRepeatable="true"/>
        <Key android:codes="10"
             android:keyLabel="ENTER"
             android:keyWidth="60%p"
             android:keyEdgeFlags="right"/>
    </Row>

</Keyboard>

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

Сурагч не продемонстрировал файлы в папке значений и предположил, что у нас есть доступ к Android Studio; что автоматически создает их. Хорошо, что у меня есть APK Builder.

E: NumPad / res / values ​​/ colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>
</resources>

F: NumPad / res / values ​​/ strings.xml

<resources>
    <string name="app_name">Suragch NumPad</string>
</resources>

G: NumPad / res / values ​​/ styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

</resources>

H: Цифровая клавиатура / AndroidManifest.xml

Это тот файл, который действительно вызывал споры. Здесь я почувствовал, что никогда не скомпилирую свою программу. рыдать. рыдать. Если вы проверите ответ Сурака, вы увидите, что он оставляет первый набор полей пустым и добавляет тег активности в этот файл. Как я уже сказал, существует четыре типа программ для Android. Активность - это обычное приложение со значком запуска. Эта цифровая клавиатура не является деятельностью! В дальнейшем никакой деятельности он не осуществлял.

Мои друзья не включают тег активности. Ваша программа скомпилируется, и при попытке запустить она вылетит! Что касается xmlns: android и uses-sdk; Я ничем не могу вам помочь. Просто попробуйте мои настройки, если они работают.

Как видите, есть сервисный тег, который регистрирует его как сервис. Также service.android:name должно быть именем службы расширения общедоступного класса в нашем java-файле. Оно ДОЛЖНО быть соответственно написано с заглавной буквы. Также пакет - это имя пакета, который мы объявили в файле java.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="Saragch.num_pad">

    <uses-sdk
        android:minSdkVersion="12"
        android:targetSdkVersion="27" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/Suragch_NumPad_icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <service
            android:name=".MyInputMethodService"
            android:label="Keyboard Display Name"
            android:permission="android.permission.BIND_INPUT_METHOD">

            <intent-filter>
                <action android:name="android.view.InputMethod"/>
            </intent-filter>

            <meta-data
                android:name="android.view.im"
                android:resource="@xml/method"/>

        </service>

    </application>
</manifest>

Я: NumPad / SRC / Saragch / num_pad / MyInputMethodService.java

Примечание: я думаю, что java - альтернатива src.

Это был еще один проблемный файл, но не такой спорный, как файл манифеста. Насколько я знаю, Java достаточно хороша, чтобы понимать, что есть что, а что нет. Я почти не знаю xml и то, как он связан с разработкой под Android!

Проблема в том, что он ничего не импортировал! Я имею в виду, он дал нам «полный» файл, в котором используются имена, которые невозможно разрешить! InputMethodService, Keyboard и т. Д. Это плохая практика, господин Сурагч. Спасибо за помощь, но как вы ожидали, что код будет скомпилирован, если имена не могут быть разрешены?

Ниже приводится правильно отредактированная версия. Я случайно наткнулся на пару намеков, чтобы отвезти меня в нужное место, чтобы узнать, что именно импортировать.

package Saragch.num_pad;

import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.KeyboardView;
import android.inputmethodservice.Keyboard;

import android.text.TextUtils;
import android.view.inputmethod.InputConnection;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;


public class MyInputMethodService extends InputMethodService implements KeyboardView.OnKeyboardActionListener 
{
    @Override
    public View onCreateInputView() 
    {
     // get the KeyboardView and add our Keyboard layout to it
     KeyboardView keyboardView = (KeyboardView)getLayoutInflater().inflate(R.layout.keyboard_view, null);
     Keyboard keyboard = new Keyboard(this, R.xml.number_pad);
     keyboardView.setKeyboard(keyboard);
     keyboardView.setOnKeyboardActionListener(this);
     return keyboardView;
    }

    @Override
    public void onKey(int primaryCode, int[] keyCodes) 
    {

        InputConnection ic = getCurrentInputConnection();

        if (ic == null) return;

        switch (primaryCode)
        {
         case Keyboard.KEYCODE_DELETE:
            CharSequence selectedText = ic.getSelectedText(0);

            if (TextUtils.isEmpty(selectedText)) 
            {
             // no selection, so delete previous character
             ic.deleteSurroundingText(1, 0);
            }

            else 
            {
             // delete the selection
             ic.commitText("", 1);
            }

            ic.deleteSurroundingText(1, 0);
            break;

         default:
            char code = (char) primaryCode;
            ic.commitText(String.valueOf(code), 1);
        }
    }

    @Override
    public void onPress(int primaryCode) { }

    @Override
    public void onRelease(int primaryCode) { }

    @Override
    public void onText(CharSequence text) { }

    @Override
    public void swipeLeft() { }

    @Override
    public void swipeRight() { }

    @Override
    public void swipeDown() { }

    @Override
    public void swipeUp() { }
}
  1. Скомпилируйте и подпишите свой проект.

    Вот где я не понимаю, как новичок в Android-разработчике. Я хотел бы изучить его вручную, так как я считаю, что настоящие программисты могут компилировать вручную.

Я думаю, что gradle - это один из инструментов для компиляции и упаковки в apk. apk похоже на файл jar или rar для zip файла. Тогда есть два типа подписи. ключ отладки, который не разрешен в игровом магазине и закрытый ключ.

Что ж, давай поможем мистеру Сарагчу. И спасибо за просмотр моего видео. Мол, подписывайтесь.

marc_s
источник
1

Была такая же проблема. Сначала я использовал макет стола, но он менялся после нажатия кнопки. Однако нашел эту страницу очень полезной. http://mobile.tutsplus.com/tutorials/android/android-user-interface-design-creating-a-numeric-keypad-with-gridlayout/

джейди
источник
3
Не уверен, где можно найти спагетти. В примере всего 5 строк кода, реализующего onCreate.
Glenn