Como você pode fazer um teclado personalizado no Android?

105

Eu quero fazer um teclado personalizado. Não sei como fazer usando XML e Java. A imagem a seguir é um modelo do teclado que desejo fazer. Necessita apenas de números.

insira a descrição da imagem aqui

XX_irmão
fonte
6
[Crie seu próprio teclado personalizado usando layouts XML para dispositivos Android] ( tutorials-android.blogspot.com/2011/06/… )
Jorgesys
1
Há um bom tutorial no Tuts: link
Hamed Ghadirian
O Google tem uma amostra do projeto "SoftKeyboard" ou há muitos recursos vinculados aqui: customkeyboarddetails.blogspot.com/2019/02/…
oliversisson

Respostas:

83

Em primeiro lugar, você precisará de um keyboard.xmlarquivo que será colocado na res/xmlpasta (se a pasta não existir, crie-a).

<?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>

** Observe que você terá que criar o backspacedrawable e colocá-lo na pasta res / drawable-ldpi com um tamanho muito pequeno (como 18x18 pixels)

Então, no arquivo xml que você deseja que seja usado (onde está o TextView), você deve adicionar o seguinte código:

<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>

** Observe que o arquivo xml em que você colocará o android.inputmethodservice.KeyboardViewdeve ser RelativeLayoutpara poder definir oalignParentBottom="true" (normalmente os teclados são apresentados na parte inferior da tela)

Então você precisa adicionar o seguinte código na onCreatefunção do Activityque lida com o que TextViewvocê deseja conectar o teclado

    // 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);

** Observe que mKeyboardemKeyboardView são variáveis ​​de classe privada que você deve criar.

Então você precisa da seguinte função para abrir o teclado (você deve associá-lo ao TextView através da onClickpropriedade 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);
    }

E, finalmente, você precisa do OnKeyboardActionListenerque tratará de seus eventos

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() {
    }
};

Espero que ajude!!!

A maior parte do código encontrado aqui

Pontios
fonte
1
E se eu não quiser que o teclado fique na parte inferior da tela? (por exemplo, quero que o usuário possa arrastá-lo). É algo que posso controlar através do meu aplicativo de teclado ou é controlado pelo sistema Android?
user3294126
a largura do teclado não está preenchendo a tela o que devo fazer para fazê-lo preencher todas as telas
George Thomas
qual é o layout pai em que o KeyboardView está? Você também verificou o layout_width do KeyboardView ??
Pontios
1
Esteja ciente de que as classes KeyboardView e Keyboard estão obsoletas pelo Google desde o nível de API 29. Portanto, esta solução não funcionará mais no futuro se você tiver que atingir um nível de API mais recente.
maex
keyboardView foi preterido pelo google. qual é a nova solução?
tohidmahmoudvand
78

Teclado do sistema

Esta resposta informa como fazer um teclado de sistema personalizado que pode ser usado em qualquer aplicativo que um usuário tenha instalado em seu telefone. Se você quiser fazer um teclado que só será usado em seu próprio aplicativo, veja minha outra resposta .

O exemplo abaixo será semelhante a este. Você pode modificá-lo para qualquer layout de teclado.

insira a descrição da imagem aqui

As etapas a seguir mostram como criar um teclado de sistema personalizado funcional. Tanto quanto possível, tentei remover qualquer código desnecessário. Se houver outros recursos de que você precisa, forneci links para mais ajuda no final.

1. Inicie um novo projeto Android

Chamei meu projeto de "Teclado Personalizado". Chame do que quiser. Não há nada mais especial aqui. Vou apenas deixar o MainActivitye "Hello World!" layout como está.

2. Adicione os arquivos de layout

Adicione os dois arquivos a seguir à res/layoutpasta do seu aplicativo :

  • keyboard_view.xml
  • key_preview.xml

keyboard_view.xml

Essa visualização é como um contêiner que conterá nosso teclado. Neste exemplo, há apenas um teclado, mas você pode adicionar outros teclados e trocá-los por dentro e por fora 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

A visualização da tecla é um layout que aparece quando você pressiona uma tecla do teclado. Mostra apenas qual tecla você está pressionando (caso seus dedos grandes e gordos a estejam cobrindo). Este não é um pop-up de múltipla escolha. Para isso, você deve verificar a visualização Candidatos .

<?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. Adicionar arquivos xml de suporte

Crie uma xmlpasta em sua respasta. (Clique com o botão direito rese escolha Novo> Diretório .)

Em seguida, adicione os dois arquivos xml a seguir a ele. (Clique com o botão direito na xmlpasta e escolha Novo> Arquivo de recurso XML .)

  • number_pad.xml
  • method.xml

number_pad.xml

É aqui que começa a ficar mais interessante. Isso Keyboarddefine o layout das teclas .

<?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>

Aqui estão algumas coisas a serem observadas:

  • keyWidth: Esta é a largura padrão de cada chave. Os 20%pmeios que cada chave deve tomar-se 20% da largura do p Arent. No entanto, pode ser substituído por teclas individuais, como você pode ver que aconteceu com as teclas Delete e Enter na terceira linha.
  • keyHeight: É codificado aqui, mas você pode usar algo como @dimen/key_heightconfigurá-lo dinamicamente para diferentes tamanhos de tela.
  • Gap: A lacuna horizontal e vertical informa quanto espaço deixar entre as teclas. Mesmo se você definir como 0px, ainda haverá uma pequena lacuna.
  • codes: Pode ser um valor Unicode ou de código personalizado que determina o que acontece ou o que é inserido quando a tecla é pressionada. Veja keyOutputTextse você deseja inserir uma string Unicode mais longa.
  • keyLabel: Este é o texto que é exibido na tecla.
  • keyEdgeFlags: Isso indica a qual borda a chave deve ser alinhada.
  • isRepeatable: Se você mantiver a tecla pressionada, ele continuará repetindo a entrada.

method.xml

Este arquivo informa ao sistema os subtipos do método de entrada que estão disponíveis. Estou apenas incluindo uma versão mínima aqui.

<?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. Adicione o código Java para lidar com a entrada de chave

Crie um novo arquivo Java. Vamos encerrar MyInputMethodService. Este arquivo liga tudo junto. Ele lida com a entrada recebida do teclado e a envia para qualquer visualização que a esteja recebendo (um EditText, por exemplo).

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() { }
}

Notas:

  • O OnKeyboardActionListenerescuta a entrada do teclado. Também requer todos os métodos vazios neste exemplo.
  • O InputConnectioné o que é usado para enviar entrada para outra visualização como um EditText.

5. Atualize o manifesto

Coloquei isso por último, em vez de primeiro, porque se refere aos arquivos que já adicionamos acima. Para registrar seu teclado personalizado como um teclado do sistema, você precisa adicionar uma serviceseção ao seu arquivo AndroidManifest.xml . Coloque na applicationseção seguinte 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>

É isso aí! Você deve conseguir executar seu aplicativo agora. No entanto, você não verá muito até habilitar o teclado nas configurações.

6. Ative o teclado em Configurações

Todo usuário que desejar utilizar o seu teclado deverá habilitá-lo nas configurações do Android. Para obter instruções detalhadas sobre como fazer isso, consulte o seguinte link:

Aqui está um resumo:

  • Vá para Configurações do Android> Idiomas e entrada> Teclado atual> Escolher teclados.
  • Você deve ver seu teclado personalizado na lista. Habilitá-lo.
  • Volte e selecione Teclado atual novamente. Você deve ver seu teclado personalizado na lista. Escolha.

Agora você deve ser capaz de usar o teclado em qualquer lugar em que possa digitar no Android.

Um estudo mais aprofundado

O teclado acima é utilizável, mas para criar um teclado que outras pessoas queiram usar, você provavelmente terá que adicionar mais funcionalidades. Estude os links abaixo para saber como.

Indo

Não gosto de como o padrão KeyboardView aparência e do comportamento ? Certamente não. Parece que não foi atualizado desde o Android 2.0. Que tal todos aqueles teclados personalizados na Play Store? Eles não se parecem em nada com o teclado feio acima.

A boa notícia é que você pode personalizar completamente a aparência e o comportamento do seu teclado. Você precisará fazer o seguinte:

  1. Crie sua própria visualização de teclado personalizada com subclasses ViewGroup. Você pode preenchê-lo com Buttons ou até mesmo fazer suas próprias visualizações-chave personalizadas dessa subclasse View. Se você usar visualizações pop-up, observe isso .
  2. Adicione uma interface de ouvinte de evento personalizado em seu teclado. Chame seus métodos para coisas como onKeyClicked(String text)ou onBackspace().
  3. Você não precisa adicionar o keyboard_view.xml, key_preview.xmlou number_pad.xmldescrito nas instruções acima, pois esses são todos para o padrão KeyboardView. Você lidará com todos esses aspectos da interface do usuário em sua visualização personalizada.
  4. Em sua MyInputMethodServiceclasse, implemente o ouvinte de teclado personalizado que você definiu em sua classe de teclado. Isso está no lugar de KeyboardView.OnKeyboardActionListener, que não é mais necessário.
  5. No método MyInputMethodServiceda sua classe onCreateInputView(), crie e retorne uma instância do seu teclado personalizado. Não se esqueça de definir o ouvinte personalizado do teclado como this.
Suragch
fonte
35

Teclado no aplicativo

Esta resposta explica como fazer um teclado personalizado para usar exclusivamente em seu aplicativo. Se você quiser fazer um teclado de sistema que possa ser usado em qualquer aplicativo, veja minha outra resposta .

O exemplo ficará assim. Você pode modificá-lo para qualquer layout de teclado.

insira a descrição da imagem aqui

1. Inicie um novo projeto Android

Eu nomeei meu projeto InAppKeyboard. Chame o seu do que você quiser.

2. Adicione os arquivos de layout

Layout do teclado

Adicione um arquivo de layout à res/layoutpasta. Liguei para o meu keyboard. O teclado será uma visualização composta personalizada que aumentaremos a partir deste arquivo de layout xml. Você pode usar qualquer layout que desejar para organizar as teclas, mas estou usando um LinearLayout. Observe as mergetags.

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>

Layout de atividade

Para fins de demonstração nossa atividade possui um único EditTexte o teclado está na parte inferior. Eu chamei minha visualização de teclado personalizado MyKeyboard. (Adicionaremos esse código em breve, portanto, ignore o erro por enquanto.) A vantagem de colocar todo o código do teclado em uma única visualização é que ele facilita a reutilização em outra atividade ou aplicativo.

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. Adicione o arquivo Java do teclado

Adicione um novo arquivo Java. Liguei para o meu MyKeyboard.

A coisa mais importante a notar aqui é que não existe um link físico para nenhum EditTextou Activity. Isso torna mais fácil conectá-lo a qualquer aplicativo ou atividade que precise dele. Esta visualização de teclado personalizado também usa um InputConnection, que imita a maneira como um teclado do sistema se comunica com um EditText. É assim que evitamos os links físicos.

MyKeyboard é uma visão composta que aumenta o layout da visão que definimos acima.

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. Aponte o teclado para EditText

Para teclados do sistema, o Android usa um InputMethodManager para apontar o teclado para o foco EditText. Neste exemplo, a atividade assumirá seu lugar fornecendo o link de EditTextpara nosso teclado personalizado para.

Como não estamos usando o teclado do sistema, precisamos desativá-lo para evitar que apareça quando tocarmos no EditText. Em segundo lugar, precisamos pegar o InputConnectiondo EditTexte dá-lo ao nosso teclado.

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);
    }
}

Se a sua Activity tiver vários EditTexts, você precisará escrever o código para passar os EditText's corretos InputConnectionpara o teclado. (Você pode fazer isso adicionando um OnFocusChangeListenere OnClickListeneraos EditTexts. Consulte este artigo para obter uma discussão sobre isso.) Você também pode ocultar ou mostrar seu teclado nos momentos apropriados.

Acabado

É isso aí. Você deve conseguir executar o aplicativo de exemplo agora e inserir ou excluir o texto conforme desejado. Seu próximo passo é modificar tudo para atender às suas necessidades. Por exemplo, em alguns de meus teclados, usei TextViews em vez de botões porque é mais fácil personalizá-los.

Notas

  • No arquivo de layout xml, você também pode usar um em TextViewvez de Buttonse quiser fazer as chaves parecerem melhores. Em seguida, basta fazer com que o fundo seja um drawable que muda o estado de aparência quando pressionado.
  • Teclados personalizados avançados: para obter mais flexibilidade na aparência e na troca de teclado, agora estou criando visualizações de teclas personalizadas que subclasse Viewe teclados personalizados que subclasse ViewGroup. O teclado apresenta todas as teclas de maneira programática. As teclas usam uma interface para se comunicar com o teclado (semelhante a como os fragmentos se comunicam com uma atividade). Isso não é necessário se você só precisar de um único layout de teclado, pois o layout xml funciona bem para isso. Mas se você quiser ver um exemplo do que venho trabalhando, verifique todas as classes Key*e aqui . Observe que também uso uma visualização de contêiner, cuja função é inserir e retirar teclados.Keyboard*
Suragch
fonte
sua resposta é ótima, mas como podemos alternar entre um teclado original e este novo teclado.
Kishan Donga
@KishanDonga, No seu teclado, você pode adicionar uma tecla para trocar de teclado. Quando o usuário pressiona, chama InputMethodManager#showInputMethodPicker(). Se o teclado original não tiver essa tecla, no entanto, a única maneira de os usuários mudarem para o seu teclado é fazendo isso manualmente nas configurações do sistema. A Apple é superior ao Android nesta área, porque a Apple requer que todos os teclados tenham uma tecla de alternância de teclado.
Suragch
@KishanDonga, acabei de perceber que essa resposta é sobre um teclado no aplicativo, não o teclado do sistema. Se você deseja alternar entre dois teclados personalizados, pode trocá-los programaticamente para dentro e para fora de uma visualização de contêiner. Basta adicionar uma tecla de troca de teclado em ambos os teclados. Veja minha nota e link sobre "teclados personalizados avançados" na resposta acima.
Suragch
Se você deseja alternar entre seu teclado e o teclado do sistema, oculte o teclado do sistema e mostre seu teclado nos momentos apropriados (e vice-versa).
Suragch
1
@MarekTakac, você precisará desabilitar o teclado do sistema e adicionar seu teclado personalizado em cada atividade. Se uma atividade tiver vários EditTexts, você precisará adicionar um onFocusChangedListenera eles para que, quando receberem o foco, você possa atribuir o InputConnectiondo atual EditTextao seu teclado personalizado.
Suragch
31

Use KeyboardView:

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

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

agora você tem o kbdque é uma visão normal.

O bom disso é que R.xml.customse refere a /res/xml/custom.xml, que define em xml o layout do teclado. Para obter mais informações sobre este arquivo, veja aqui: Keyboard , Keyboard.Row , Keyboard.Key .

bigstones
fonte
2
Estou usando a classe KeyboardView, mas a partir da API 29, ela está obsoleta.
Abhijit
14

Aqui está um projeto de amostra para um teclado virtual.

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

O seu deve estar nas mesmas linhas com um layout diferente.

Edit: Se você precisa do teclado apenas em seu aplicativo, é muito simples! Crie um layout linear com orientação vertical e crie 3 layouts lineares dentro dele com orientação horizontal. Em seguida, coloque os botões de cada linha em cada um desses layouts lineares horizontais e atribua a propriedade de peso aos botões. Use android: layout_weight = 1 para todos eles, para que fiquem igualmente espaçados.

Isso vai resolver. Se você não obteve o que esperava, poste o código aqui e estamos aqui para ajudá-lo!

nithinreddy
fonte
A edição é realmente ruim porque isso significaria que o teclado é sempre mostrado e não se comportará como o teclado padrão do Android.
m0skit0
4

Eu me deparei com este post recentemente quando estava tentando decidir qual método usar para criar meu próprio teclado personalizado. Achei a API do sistema Android muito limitada, então decidi fazer meu próprio teclado no aplicativo. Usando a resposta de Suragch como base para minha pesquisa, passei a projetar meu próprio componente de teclado . Foi postado no GitHub com uma licença do MIT. Esperançosamente, isso poupará muito tempo e dor de cabeça para outra pessoa.

A arquitetura é bastante flexível. Há uma visualização principal (CustomKeyboardView) que você pode injetar com qualquer layout de teclado e controlador que desejar.

Você só precisa declarar CustomKeyboardView em seu xml de atividade (você também pode fazer isso programaticamente):

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

Em seguida, registre seus EditText's com ele e diga que tipo de teclado eles devem usar:

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)
}

O CustomKeyboardView trata do resto!

Eu tenho a bola rolando com um teclado numérico, NumberDecimal e QWERTY. Fique à vontade para baixá-lo e criar seus próprios layouts e controladores. Se parece com isso:

paisagem gif do teclado personalizado do Android

insira a descrição da imagem aqui

Mesmo que esta não seja a arquitetura que você decidir usar, espero que seja útil ver o código-fonte de um teclado integrado no aplicativo.

Novamente, aqui está o link para o projeto: Teclado personalizado no aplicativo

Don Brody
fonte
2

Bem, Suragch deu a melhor resposta até agora, mas ele pulou algumas coisas menores que eram importantes para obter o aplicativo compilado.

Espero dar uma resposta melhor do que Suragch, melhorando sua resposta. Vou adicionar todos os elementos que faltam que ele não colocou.

Compilei meu apk usando o aplicativo Android, APK Builder 1.1.0. Então, vamos começar.

Para construir um aplicativo Android, precisamos de alguns arquivos e pastas organizados em um determinado formato e capitalizados de acordo.

layout res -> arquivos xml que descrevem a aparência do aplicativo no telefone. Semelhante a como o html molda a aparência da página da web no navegador. Permitindo que seu aplicativo caiba nas telas de acordo.

valores -> dados constantes, como colors.xml, strings.xml, styles.xml. Esses arquivos devem ser escritos corretamente.

drawable -> fotos {jpeg, png, ...}; Nomeie-os qualquer coisa.

mipmap -> mais fotos. usado para o ícone do aplicativo?

xml -> mais arquivos xml.

src -> atua como JavaScript em html. os arquivos de layout iniciarão a visualização inicial e seu arquivo java controlará dinamicamente os elementos de tag e os eventos de gatilho. Os eventos também podem ser ativados diretamente no layout.xml, assim como no html.

AndroidManifest.xml -> Este arquivo registra do que trata seu aplicativo. Nome do aplicativo, tipo de programa, permissões necessárias, etc. Isso parece tornar o Android bastante seguro. Os programas literalmente não podem fazer o que não pediram no Manifesto.

Agora, existem 4 tipos de programas Android, uma atividade, um serviço, um provedor de conteúdo e um receptor de transmissão. Nosso teclado será um serviço, o que permite que ele seja executado em segundo plano. Ele não aparecerá na lista de aplicativos a serem iniciados; mas pode ser desinstalado.

Para compilar seu aplicativo, envolve gradle e assinatura de apk. Você pode pesquisar esse ou usar o APK Builder para Android. É super fácil.

Agora que entendemos o desenvolvimento do Android, vamos criar os arquivos e pastas.

  1. Crie os arquivos e pastas conforme discutido acima. Meu diretório será o seguinte:

    • NumPad
      • AndroidManifest.xml
      • src
        • Saragch
          • num_pad
            • MyInputMethodService.java
      • res
        • desenhavel
          • Suragch_NumPad_icon.png
        • layout
          • key_preview.xml
          • keyboard_view.xml
        • xml
          • method.xml
          • number_pad.xml
        • valores
          • colors.xml
          • strings.xml
          • styles.xml

Lembre-se de que se você estiver usando um ide como o Android Studio, ele pode ter um arquivo de projeto.

  1. Grave arquivos.

A: 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: teclado numérico / 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>

Claro que isso pode ser facilmente editado ao seu gosto. Você pode até usar imagens em vez de palavras para o rótulo.

Suragch não demonstrou os arquivos na pasta de valores e presumiu que tínhamos acesso ao Android Studio; que os cria automaticamente. Ainda bem que tenho o 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: Numpad / AndroidManifest.xml

Este é o arquivo que realmente estava em disputa. Aqui eu senti que nunca iria compilar meu programa. soluço. soluço. Se você verificar a resposta de Suracgh, verá que ele deixa o primeiro conjunto de campos vazio e adiciona a tag de atividade neste arquivo. Como eu disse, existem quatro tipos de programas Android. Uma atividade é um aplicativo normal com um ícone de inicialização. Este teclado numérico não é uma atividade! Além disso, ele não implementou nenhuma atividade.

Meus amigos não incluem a tag de atividade. Seu programa irá compilar e, quando você tentar iniciá-lo, irá travar! Quanto a xmlns: android e uses-sdk; Eu não posso te ajudar nisso. Tente minhas configurações se elas funcionarem.

Como você pode ver, existe uma etiqueta de serviço, que o registra como um serviço. Além disso, service.android:name deve ser o nome do serviço de extensão de classe pública em nosso arquivo java. DEVE ser capitalizado de acordo. Além disso, pacote é o nome do pacote que declaramos no arquivo 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>

I: NumPad / src / Saragch / num_pad / MyInputMethodService.java

Observação: acho que java é uma alternativa ao src.

Esse era outro arquivo problemático, mas não tão polêmico quanto o arquivo de manifesto. Como eu conheço Java bom o suficiente para saber o que é o quê, o que não é. Eu mal conheço xml e como ele se relaciona com o desenvolvimento do Android!

O problema aqui era que ele não importava nada! Quer dizer, ele nos deu um arquivo "completo" que usa nomes que não puderam ser resolvidos! InputMethodService, Keyboard, etc. Isso é uma má prática, Sr. Suragch. Obrigado por me ajudar, mas como você esperava que o código fosse compilado se os nomes não pudessem ser resolvidos?

A seguir está a versão editada corretamente. Acontece que eu aproveitei algumas dicas que me levaram ao lugar certo para aprender o que exatamente importar.

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. Compile e assine seu projeto.

    É aqui que estou sem noção como um novo desenvolvedor Android. Gostaria de aprender manualmente, pois acredito que programadores reais podem compilar manualmente.

Acho que o gradle é uma das ferramentas para compilar e empacotar para apk. O apk parece ser um arquivo jar ou um arquivo rar para zip. Existem então dois tipos de assinatura. chave de depuração que não é permitida na Play Store e chave privada.

Bem, vamos dar uma mão ao Sr. Saragch. E obrigado por assistir meu vídeo. Tipo, se inscreva.

marc_s
fonte