¿Cómo se puede hacer un teclado personalizado en Android?

105

Quiero hacer un teclado personalizado. No sé cómo hacerlo usando XML y Java. La siguiente imagen es un modelo del teclado que quiero hacer. Solo necesita números.

ingrese la descripción de la imagen aquí

XX_brother
fuente
6
[Cree su propio teclado personalizado usando diseños XML para dispositivos Android] ( tutorials-android.blogspot.com/2011/06/… )
Jorgesys
1
Hay un buen tutorial en Tuts: enlace
Hamed Ghadirian
Google tiene un proyecto de muestra "SoftKeyboard", o hay bastantes recursos vinculados aquí: customkeyboarddetails.blogspot.com/2019/02/…
oliversisson

Respuestas:

83

En primer lugar, necesitará un keyboard.xmlarchivo que se colocará en la res/xmlcarpeta (si la carpeta no existe, créelo).

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

** Tenga en cuenta que tendrá que crear el backspacedibujable y colocarlo en la carpeta res / drawable-ldpi con un tamaño muy pequeño (como 18x18 píxeles)

Luego, en el archivo xml que desea que se use (donde se encuentra su TextView), debe agregar el siguiente 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>

** Tenga en cuenta que el archivo xml en el que colocará el android.inputmethodservice.KeyboardView, debe ser RelativeLayoutpara poder configurar el alignParentBottom="true"(por lo general, los teclados se presentan en la parte inferior de la pantalla)

Luego, debe agregar el siguiente código en la onCreatefunción del Activityque maneja el TextViewque desea adjuntar el 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);

** Tenga en cuenta que mKeyboardy mKeyboardViewson variables de clase privadas que debe crear.

Entonces necesita la siguiente función para abrir el teclado (debe asociarlo con TextView a través de la onClickpropiedad 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);
    }

Y finalmente necesitas el OnKeyboardActionListenerque se encargará de tus 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 ayude!!!

La mayor parte del código que se encuentra aquí

Pontios
fuente
1
¿Qué pasa si no quiero que el teclado esté en la parte inferior de la pantalla? (por ejemplo, quiero que el usuario pueda arrastrarlo). ¿Es eso algo que puedo controlar a través de mi aplicación de teclado o lo maneja el sistema Android?
user3294126
el ancho del teclado no llena la pantalla, ¿qué debo hacer para que ocupe todas las pantallas?
George Thomas
¿Cuál es el diseño principal en el que se encuentra KeyboardView? ¿También ha comprobado el layout_width del KeyboardView?
Pontios
1
Tenga en cuenta que Google ha desaprobado las clases KeyboardView y Keyboard desde el nivel de API 29. Por lo tanto, esta solución ya no funcionará en el futuro si tiene que apuntar a un nivel de API más nuevo.
maex
keyboardView está en desuso por Google. ¿Qué es nueva solución?
tohidmahmoudvand
78

Teclado del sistema

Esta respuesta le dice cómo hacer un teclado de sistema personalizado que se pueda usar en cualquier aplicación que un usuario haya instalado en su teléfono. Si desea hacer un teclado que solo se usará dentro de su propia aplicación, vea mi otra respuesta .

El siguiente ejemplo se verá así. Puede modificarlo para cualquier distribución de teclado.

ingrese la descripción de la imagen aquí

Los siguientes pasos muestran cómo crear un teclado de sistema personalizado que funcione. En la medida de lo posible, intenté eliminar cualquier código innecesario. Si hay otras funciones que necesita, al final proporcioné enlaces para obtener más ayuda.

1. Inicie un nuevo proyecto de Android

Llamé a mi proyecto "Teclado personalizado". Llámalo como quieras. No hay nada más especial aquí. Solo dejaré MainActivityy "¡Hola mundo!" diseño como está.

2. Agregue los archivos de diseño

Agregue los siguientes dos archivos a su aplicación res/layout carpeta de :

  • keyboard_view.xml
  • key_preview.xml

keyboard_view.xml

Esta vista es como un contenedor que contendrá nuestro teclado. En este ejemplo, solo hay un teclado, pero puede agregar otros teclados e intercambiarlos dentro y fuera de este 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

La vista previa de la tecla es un diseño que aparece cuando presiona una tecla del teclado. Solo muestra qué tecla está presionando (en caso de que sus dedos grandes y gordos la cubran). Esta no es una ventana emergente de opción múltiple. Para eso, debe consultar la vista de 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. Agregue archivos xml de soporte

Crea una xmlcarpeta en tu rescarpeta. (Haga clic derecho resy elija Nuevo> Directorio ).

Luego agregue los siguientes dos archivos xml. (Haga clic con el botón derecho en la xmlcarpeta y elija Nuevo> Archivo de recursos XML ).

  • number_pad.xml
  • método.xml

number_pad.xml

Aquí es donde comienza a ponerse más interesante. Esto Keyboarddefine el diseño de las claves .

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

Aquí hay algunas cosas a tener en cuenta:

  • keyWidth: Este es el ancho predeterminado de cada tecla. Esto 20%psignifica que cada tecla debe ocupar el 20% del ancho de la p arent. Sin embargo, se puede anular con teclas individuales, como puede ver que sucedió con las teclas Eliminar e Intro en la tercera fila.
  • keyHeight: Está codificado aquí, pero podría usar algo como @dimen/key_heightconfigurarlo dinámicamente para diferentes tamaños de pantalla.
  • Gap: El espacio horizontal y vertical indica cuánto espacio dejar entre las teclas. Incluso si lo configura en0px todavía hay un pequeño espacio.
  • codes: Puede ser un valor de código Unicode o personalizado que determina qué sucede o qué se ingresa cuando se presiona la tecla. Vea keyOutputTextsi desea ingresar una cadena Unicode más larga.
  • keyLabel: Este es el texto que se muestra en la tecla.
  • keyEdgeFlags: Esto indica con qué borde debe alinearse la llave.
  • isRepeatable: Si mantiene presionada la tecla, seguirá repitiendo la entrada.

método.xml

Este archivo le dice al sistema los subtipos de métodos de entrada que están disponibles. Solo incluyo una versión mínima aquí.

<?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. Agregue el código Java para manejar la entrada clave.

Cree un nuevo archivo Java. Vamos a llamarlo MyInputMethodService. Este archivo une todo. Maneja la entrada recibida del teclado y la envía a cualquier vista que la reciba (una EditText, por ejemplo).

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:

  • los OnKeyboardActionListener escucha la entrada del teclado. También requiere todos esos métodos vacíos en este ejemplo.
  • El InputConnectiones lo que se utiliza para enviar la entrada a otra vista como una EditText.

5. Actualiza el manifiesto

Pongo esto último en lugar de primero porque se refiere a los archivos que ya agregamos anteriormente. Para registrar su teclado personalizado como un teclado del sistema, debe agregar una servicesección a su archivo AndroidManifest.xml . Ponlo en la applicationsección siguiente 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>

¡Eso es! Debería poder ejecutar su aplicación ahora. Sin embargo, no verá mucho hasta que habilite su teclado en la configuración.

6. Habilite el teclado en Configuración

Todos los usuarios que quieran usar su teclado deberán habilitarlo en la configuración de Android. Para obtener instrucciones detalladas sobre cómo hacerlo, consulte el siguiente enlace:

He aquí un resumen:

  • Vaya a Configuración de Android> Idiomas y entrada> Teclado actual> Elegir teclados.
  • Debería ver su teclado personalizado en la lista. Permitirle.
  • Regrese y elija Teclado actual nuevamente. Debería ver su teclado personalizado en la lista. Elígelo.

Ahora debería poder usar su teclado en cualquier lugar donde pueda escribir en Android.

Estudio adicional

El teclado de arriba es utilizable, pero para crear un teclado que otras personas quieran usar, probablemente tendrá que agregar más funciones. Estudie los enlaces a continuación para aprender cómo.

Continuando

No me gusta como el estándar KeyboardView ve y se comporta ? Ciertamente no lo hago. Parece que no se ha actualizado desde Android 2.0. ¿Qué tal todos esos teclados personalizados en Play Store? No se parecen en nada al feo teclado de arriba.

La buena noticia es que puede personalizar completamente el aspecto y el comportamiento de su propio teclado. Deberá hacer lo siguiente:

  1. Cree su propia vista de teclado personalizada que subclases ViewGroup. Puede llenarlo con Buttons o incluso crear sus propias vistas clave personalizadas para esa subclase View. Si usa vistas emergentes, tenga en cuenta esto .
  2. Agregue una interfaz de escucha de eventos personalizada en su teclado. Llame a sus métodos para cosas como onKeyClicked(String text)o onBackspace().
  3. No es necesario agregar el keyboard_view.xml, key_preview.xmlo se number_pad.xmldescribe en las instrucciones anteriores, ya que estos son todos para elKeyboardView . Manejará todos estos aspectos de la interfaz de usuario en su vista personalizada.
  4. En su MyInputMethodServiceclase, implemente el oyente de teclado personalizado que definió en su clase de teclado. Esto está en lugar de KeyboardView.OnKeyboardActionListener, que ya no es necesario.
  5. En MyInputMethodServiceel onCreateInputView()método de su clase , cree y devuelva una instancia de su teclado personalizado. No olvide configurar el oyente personalizado del teclado en this.
Suragch
fuente
35

Teclado en la aplicación

Esta respuesta le dice cómo hacer un teclado personalizado para usar exclusivamente dentro de su aplicación. Si desea crear un teclado de sistema que se pueda usar en cualquier aplicación, consulte mi otra respuesta .

El ejemplo se verá así. Puede modificarlo para cualquier distribución de teclado.

ingrese la descripción de la imagen aquí

1. Inicie un nuevo proyecto de Android

Nombré mi proyecto InAppKeyboard. Llama al tuyo como quieras.

2. Agregue los archivos de diseño

Diseño del teclado

Agregue un archivo de diseño a la res/layoutcarpeta. Llamé al mío keyboard. El teclado será una vista compuesta personalizada que inflaremos a partir de este archivo de diseño xml. Puede usar el diseño que desee para organizar las claves, pero estoy usando un archivo LinearLayout. Tenga en cuenta las mergeetiquetas.

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>

Diseño de actividad

Para fines de demostración nuestra actividad tiene un solo EditTexty el teclado está en la parte inferior. Llamé a mi vista de teclado personalizadaMyKeyboard . (Agregaremos este código pronto, así que ignore el error por ahora). La ventaja de poner todo el código de nuestro teclado en una sola vista es que facilita su reutilización en otra actividad o aplicación.

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. Agregue el archivo Java Keyboard

Agregue un nuevo archivo Java. Llamé al mío MyKeyboard.

Lo más importante a tener en cuenta aquí es que no hay un vínculo físico a ninguno EditTexto Activity. Esto facilita su conexión a cualquier aplicación o actividad que lo necesite. Esta vista de teclado personalizado también utiliza un InputConnection, que imita la forma en que un teclado del sistema se comunica con un EditText. Así es como evitamos los enlaces duros.

MyKeyboard es una vista compuesta que infla el diseño de vista que definimos anteriormente.

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. Apunte con el teclado a EditText

Para los teclados del sistema, Android usa un InputMethodManager para apuntar el teclado al foco EditText. En este ejemplo, la actividad ocupará su lugar proporcionando el enlace desde el EditTexta nuestro teclado personalizado a.

Como no estamos usando el teclado del sistema, debemos desactivarlo para evitar que aparezca cuando tocamos EditText. En segundo lugar, necesitamos obtener el InputConnectiondel EditTexty dárselo a nuestro 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);
    }
}

Si su actividad tiene varios EditTexts, deberá escribir código para pasar los EditText correctos InputConnectional teclado. (Puede hacer esto agregando un OnFocusChangeListenery OnClickListenera EditTexts. Vea este artículo para una discusión de eso). También puede querer ocultar o mostrar su teclado en los momentos apropiados.

Terminado

Eso es. Debería poder ejecutar la aplicación de ejemplo ahora e ingresar o eliminar texto como desee. El siguiente paso es modificar todo para adaptarlo a sus propias necesidades. Por ejemplo, en algunos de mis teclados he usado TextViews en lugar de Buttons porque es más fácil personalizarlos.

Notas

  • En el archivo de diseño xml, también puede usar un TextViewpoco a Buttonsi desea que las claves se vean mejor. Luego, haga que el fondo sea un dibujable que cambie el estado de apariencia cuando se presiona.
  • Teclados personalizados avanzados: para una mayor flexibilidad en la apariencia del teclado y el cambio de teclado, ahora estoy creando vistas de teclas personalizadas en esa subclase Viewy teclados personalizados en esa subclase ViewGroup. El teclado presenta todas las teclas mediante programación. Las teclas usan una interfaz para comunicarse con el teclado (similar a cómo los fragmentos se comunican con una actividad). Esto no es necesario si solo necesita un diseño de teclado único, ya que el diseño xml funciona bien para eso. Pero si quieres ver un ejemplo de lo que he estado trabajando, mira todas las clases Key*y aquí . Tenga en cuenta que también utilizo una vista de contenedor cuya función es intercambiar teclados hacia adentro y hacia afuera.Keyboard*
Suragch
fuente
su respuesta es genial, pero ¿cómo podemos establecer alternar entre un teclado original y este nuevo teclado?
Kishan Donga
@KishanDonga, en tu teclado puedes agregar una tecla para cambiar de teclado. Cuando el usuario lo presiona llamar InputMethodManager#showInputMethodPicker(). Sin embargo, si el teclado original no tiene esa tecla, la única forma en que los usuarios pueden cambiar a su teclado es hacerlo manualmente en la configuración del sistema. Apple es superior a Android en esta área, porque Apple requiere que todos los teclados tengan una tecla de cambio de teclado.
Suragch
@KishanDonga, me acabo de dar cuenta de que esta respuesta se trata de un teclado en la aplicación, no del teclado del sistema. Si desea intercambiar entre dos teclados personalizados, puede intercambiarlos mediante programación dentro y fuera de una vista de contenedor. Simplemente agregue una tecla de intercambio de teclados en ambos teclados. Vea mi nota y enlace "teclados personalizados avanzados" en la respuesta anterior.
Suragch
Si desea alternar entre su teclado y el teclado del sistema, oculte el teclado del sistema y muestre su teclado en los momentos apropiados (y viceversa).
Suragch
1
@MarekTakac, deberá deshabilitar el teclado del sistema y agregar su teclado personalizado en cada actividad. Si una actividad tiene varios EditTexts, deberá agregarles un valor onFocusChangedListenerpara que, cuando reciban el foco, pueda asignarlos InputConnectiondesde el actual EditTexta su teclado personalizado.
Suragch
31

Utilizar KeyboardView:

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

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

ahora tienes lo kbdque es una vista normal.

Lo bueno de esto es que se R.xml.customrefiere a /res/xml/custom.xml, que define en xml la distribución del teclado. Para obtener más información sobre este archivo, busque aquí: Keyboard , Keyboard.Row , Keyboard.Key .

piedras grandes
fuente
2
Estoy usando la clase KeyboardView, pero a partir de API 29, ahora está en desuso.
Abhijit
14

Aquí hay un proyecto de muestra para un teclado virtual.

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

El suyo debe estar en las mismas líneas con un diseño diferente.

Editar: Si necesita el teclado solo en su aplicación, ¡es muy simple! Cree un diseño lineal con orientación vertical y cree 3 diseños lineales en su interior con orientación horizontal. Luego coloque los botones de cada fila en cada uno de esos diseños lineales horizontales y asigne la propiedad de peso a los botones. Use android: layout_weight = 1 para todos ellos, para que estén igualmente espaciados.

Esto solucionará. Si no obtuvo lo que esperaba, publique el código aquí, ¡y estamos aquí para ayudarlo!

nithinreddy
fuente
La edición es realmente mala porque eso significaría que el teclado siempre se muestra y no se comportará como el teclado estándar de Android.
m0skit0
4

Encontré esta publicación recientemente cuando estaba tratando de decidir qué método usar para crear mi propio teclado personalizado. Descubrí que la API del sistema Android era muy limitada, así que decidí crear mi propio teclado en la aplicación. Usando la respuesta de Suragch como base para mi investigación, continué diseñando mi propio componente de teclado . Está publicado en GitHub con una licencia MIT. Con suerte, esto le ahorrará a otra persona mucho tiempo y dolor de cabeza.

La arquitectura es bastante flexible. Hay una vista principal (CustomKeyboardView) que puede inyectar con cualquier distribución de teclado y controlador que desee.

Solo tiene que declarar CustomKeyboardView en su xml de actividad (también puede hacerlo mediante programación):

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

Luego registre su EditText con él y dígale qué tipo de teclado deben 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)
}

¡CustomKeyboardView se encarga del resto!

Tengo la pelota rodando con un teclado numérico, numérico decimal y QWERTY. No dude en descargarlo y crear sus propios diseños y controladores. Se parece a esto:

android teclado personalizado gif paisaje

ingrese la descripción de la imagen aquí

Incluso si esta no es la arquitectura con la que decide ir, con suerte será útil ver el código fuente de un teclado en la aplicación que funcione.

Nuevamente, aquí está el enlace al proyecto: Teclado personalizado en la aplicación

Don Brody
fuente
2

Bueno, Suragch dio la mejor respuesta hasta ahora, pero omitió ciertas cosas menores que eran importantes para compilar la aplicación.

Espero dar una mejor respuesta que Suragch mejorando su respuesta. Agregaré todos los elementos que faltan que no puso.

Compilé mi apk usando la aplicación de Android, APK Builder 1.1.0. Vamos a empezar.

Para crear una aplicación de Android, necesitamos un par de archivos y carpetas que estén organizados en un formato determinado y en mayúsculas en consecuencia.

diseño res -> archivos xml que muestran cómo se verá la aplicación en el teléfono. Similar a cómo html da forma al aspecto de la página web en el navegador. Permitir que su aplicación se ajuste a las pantallas en consecuencia.

valores -> datos constantes como colors.xml, strings.xml, styles.xml. Estos archivos deben estar escritos correctamente.

dibujable -> imágenes {jpeg, png, ...}; Nómbrelos cualquier cosa.

mipmap -> más fotos. utilizado para el icono de la aplicación?

xml -> más archivos xml.

src -> actúa como JavaScript en html. Los archivos de diseño iniciarán la vista inicial y su archivo Java controlará dinámicamente los elementos de la etiqueta y los eventos de activación. Los eventos también se pueden activar directamente en layout.xml al igual que en html.

AndroidManifest.xml -> Este archivo registra de qué se trata su aplicación. Nombre de la aplicación, tipo de programa, permisos necesarios, etc. Esto parece hacer que Android sea bastante seguro. Los programas, literalmente, no pueden hacer lo que no pidieron en el Manifiesto.

Ahora hay 4 tipos de programas de Android: una actividad, un servicio, un proveedor de contenido y un receptor de transmisión. Nuestro teclado será un servicio que permitirá que se ejecute en segundo plano. No aparecerá en la lista de aplicaciones para iniciar; pero se puede desinstalar.

Para compilar su aplicación, implica la firma de Gradle y apk. Puedes investigar ese o usar APK Builder para Android. Es superfácil.

Ahora que entendemos el desarrollo de Android, creemos los archivos y carpetas.

  1. Cree los archivos y carpetas como comenté anteriormente. Mi directorio se verá de la siguiente manera:

    • NumPad
      • AndroidManifest.xml
      • src
        • Saragch
          • num_pad
            • MyInputMethodService.java
      • res
        • dibujable
          • Suragch_NumPad_icon.png
        • diseño
          • key_preview.xml
          • keyboard_view.xml
        • xml
          • método.xml
          • number_pad.xml
        • valores
          • colors.xml
          • strings.xml
          • styles.xml

Recuerde que si está utilizando un ide como Android Studio, puede tener un archivo de proyecto.

  1. Escribe archivos.

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

Por supuesto, esto se puede editar fácilmente a su gusto. Incluso puede utilizar imágenes en lugar de palabras para la etiqueta.

Suragch no demostró los archivos en la carpeta de valores y asumió que teníamos acceso a Android Studio; que los crea automáticamente. Menos mal que tengo 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: teclado numérico / AndroidManifest.xml

Este es el archivo que realmente estaba en disputa. Aquí sentí que nunca compilaría mi programa. sollozo. sollozo. Si verifica la respuesta de Suracgh, verá que deja el primer conjunto de campos vacío y agrega la etiqueta de actividad en este archivo. Como dije, hay cuatro tipos de programas de Android. Una actividad es una aplicación normal con un icono de inicio. ¡Este teclado numérico no es una actividad! Además, no implementó ninguna actividad.

Mis amigos no incluyen la etiqueta de actividad. Su programa se compilará y, cuando intente ejecutarlo, se bloqueará. En cuanto a xmlns: android y uses-sdk; No puedo ayudarte en eso. Pruebe mi configuración si funciona.

Como puede ver, hay una etiqueta de servicio, que lo registra como un servicio. También service.android:name debe ser el nombre de la clase pública que extiende el servicio en nuestro archivo java. DEBE estar en mayúscula en consecuencia. También paquete es el nombre del paquete que declaramos en el archivo 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>

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

Nota: creo que java es una alternativa a src.

Este era otro archivo problemático pero no tan polémico como el archivo de manifiesto. Como sé Java lo suficientemente bueno como para saber qué es qué, qué no lo es. ¡Apenas conozco XML y cómo se relaciona con el desarrollo de Android!

¡El problema aquí era que no importaba nada! Quiero decir, ¡nos dio un archivo "completo" que usa nombres que no se pudieron resolver! InputMethodService, Keyboard, etc. Esa es una mala práctica, Sr. Suragch. Gracias por ayudarme, pero ¿cómo esperaba que se compilara el código si los nombres no se pueden resolver?

A continuación se muestra la versión correctamente editada. Simplemente me abalancé sobre un par de pistas que me llevaron al lugar correcto para saber qué importar exactamente.

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. Compila y firma tu proyecto.

    Aquí es donde no tengo ni idea como nuevo desarrollador de Android. Me gustaría aprenderlo manualmente, ya que creo que los programadores reales pueden compilar manualmente.

Creo que gradle es una de las herramientas para compilar y empaquetar en apk. apk parece ser como un archivo jar o un rar para un archivo zip. Entonces hay dos tipos de firma. clave de depuración que no está permitida en Play Store y clave privada.

Bueno, echemos una mano al Sr. Saragch. Y gracias por ver mi video. Me gusta, suscríbete.

marc_s
fuente