Come puoi creare una tastiera personalizzata in Android?


105

Voglio creare una tastiera personalizzata. Non so come farlo usando XML e Java. L'immagine seguente è un modello della tastiera che voglio realizzare. Ha bisogno solo di numeri.

inserisci qui la descrizione dell'immagine


6
[Crea la tua tastiera personalizzata utilizzando layout XML per dispositivi Android] ( tutorials-android.blogspot.com/2011/06/… )
Jorgesys

1
C'è un buon tutorial su Tuts: link
Hamed Ghadirian

Google ha un progetto di esempio "SoftKeyboard" o ci sono molte risorse collegate qui: customkeyboarddetails.blogspot.com/2019/02/…
oliversisson

Risposte:


83

Prima di tutto avrai bisogno di un keyboard.xmlfile che verrà inserito nella res/xmlcartella (se la cartella non esiste, creala).

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

** Nota che dovrai creare il backspacedrawable e posizionarlo nella cartella res / drawable-ldpi con una dimensione molto piccola (come 18x18 pixel)

Quindi nel file xml che vuoi che venga utilizzato (dove si trova il tuo TextView) dovresti aggiungere il seguente codice:

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

** Nota che il file xml in cui inserirai android.inputmethodservice.KeyboardView, deve essere RelativeLayoutper poter impostare il alignParentBottom="true"(Di solito le tastiere sono presentate nella parte inferiore dello schermo)

Quindi è necessario aggiungere il seguente codice nella onCreatefunzione del Activityche gestisce il a cui TextViewsi desidera collegare la tastiera

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

** Nota che mKeyboarde mKeyboardViewsono variabili di classe privata che devi creare.

Quindi è necessaria la seguente funzione per aprire la tastiera (è necessario associarla al TextView tramite la onClickproprietà 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 hai bisogno del OnKeyboardActionListenerche gestirà i tuoi eventi

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

Spero che aiuti!!!

La maggior parte del codice si trova qui


1
Cosa succede se non voglio che la tastiera si trovi nella parte inferiore dello schermo? (ad esempio, voglio che l'utente sia in grado di trascinarlo). È qualcosa che posso controllare tramite la mia app per tastiera o è gestito dal sistema Android?
user3294126

la larghezza della tastiera non riempie lo schermo cosa devo fare per riempire tutti gli schermi
George Thomas

qual è il layout principale in cui si trova il KeyboardView? Hai anche controllato il layout_width di KeyboardView ??
Pontios

1
Tieni presente che le classi KeyboardView e Keyboard sono deprecate da Google a partire dal livello API 29. Quindi questa soluzione non funzionerà più in futuro se devi scegliere come target un livello API più recente.
maex

keyboardView è deprecato da Google. qual è la nuova soluzione?
tohidmahmoudvand

78

Tastiera di sistema

Questa risposta spiega come creare una tastiera di sistema personalizzata che può essere utilizzata in qualsiasi app che un utente ha installato sul proprio telefono. Se vuoi creare una tastiera che verrà utilizzata solo all'interno della tua app, guarda la mia altra risposta .

L'esempio seguente sarà simile a questo. Puoi modificarlo per qualsiasi layout di tastiera.

inserisci qui la descrizione dell'immagine

I passaggi seguenti mostrano come creare una tastiera di sistema personalizzata funzionante. Per quanto possibile ho provato a rimuovere qualsiasi codice non necessario. Se ci sono altre funzionalità di cui hai bisogno, ho fornito collegamenti a ulteriore aiuto alla fine.

1. Avvia un nuovo progetto Android

Ho chiamato il mio progetto "Tastiera personalizzata". Chiamalo come vuoi. Non c'è nient'altro di speciale qui. Lascerò solo il MainActivitye "Hello World!" layout così com'è.

2. Aggiungere i file di layout

Aggiungi i seguenti due file alla res/layoutcartella della tua app :

  • keyboard_view.xml
  • key_preview.xml

keyboard_view.xml

Questa vista è come un contenitore che terrà la nostra tastiera. In questo esempio c'è una sola tastiera, ma puoi aggiungere altre tastiere e scambiarle dentro e fuori da questa 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

L'anteprima dei tasti è un layout che viene visualizzato quando si preme un tasto della tastiera. Mostra solo quale tasto stai premendo (nel caso in cui le tue dita grandi e grasse lo coprano). Questo non è un popup a scelta multipla. Per questo dovresti controllare la vista Candidati .

<?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. Aggiungere file xml di supporto

Crea una xmlcartella nella tua rescartella. (Fare clic con il pulsante destro del mouse rese scegliere Nuovo> Directory .)

Quindi aggiungi i seguenti due file xml. (Fare clic con il pulsante destro del mouse sulla xmlcartella e scegliere Nuovo> File di risorse XML .)

  • number_pad.xml
  • method.xml

number_pad.xml

È qui che inizia a diventare più interessante. Questo Keyboarddefinisce il layout dei tasti .

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

Ecco alcune cose da notare:

  • keyWidth: Questa è la larghezza predefinita di ogni chiave. I 20%pmezzi che ogni chiave dovrebbe occupare il 20% della larghezza del p Arent. Può essere sovrascritto da singoli tasti, tuttavia, come puoi vedere è successo con i tasti Elimina e Invio nella terza riga.
  • keyHeight: È hard coded qui, ma potresti usare qualcosa di simile @dimen/key_heightper impostarlo dinamicamente per diverse dimensioni dello schermo.
  • Gap: La distanza orizzontale e verticale indica quanto spazio lasciare tra i tasti. Anche se lo imposti, 0pxc'è ancora un piccolo spazio vuoto.
  • codes: Può essere un valore Unicode o un codice personalizzato che determina cosa accade o cosa viene immesso quando viene premuto il tasto. Verifica keyOutputTextse vuoi inserire una stringa Unicode più lunga.
  • keyLabel: Questo è il testo visualizzato sulla chiave.
  • keyEdgeFlags: Indica a quale bordo deve essere allineata la chiave.
  • isRepeatable: Se tieni premuto il tasto, continuerà a ripetere l'input.

method.xml

Questo file indica al sistema i sottotipi del metodo di input disponibili. Sto solo includendo una versione minima qui.

<?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. Aggiungere il codice Java per gestire l'immissione della chiave

Crea un nuovo file Java. Chiamiamolo MyInputMethodService. Questo file lega tutto insieme. Gestisce l'input ricevuto dalla tastiera e lo invia a qualsiasi vista lo stia ricevendo (una EditText, ad esempio).

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

Appunti:

  • I OnKeyboardActionListenerascolti per l'input dalla tastiera. Richiede anche tutti quei metodi vuoti in questo esempio.
  • La InputConnectionè quello che viene utilizzato per inviare input per un'altra vista come un EditText.

5. Aggiorna il manifest

Metto quest'ultimo anziché il primo perché si riferisce ai file che abbiamo già aggiunto sopra. Per registrare la tua tastiera personalizzata come tastiera di sistema, devi aggiungere una servicesezione al tuo file AndroidManifest.xml . Mettilo nella applicationsezione dopo 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>

Questo è tutto! Ora dovresti essere in grado di eseguire la tua app. Tuttavia, non vedrai molto finché non abiliti la tastiera nelle impostazioni.

6. Abilitare la tastiera in Impostazioni

Ogni utente che desidera utilizzare la tastiera dovrà abilitarlo nelle impostazioni di Android. Per istruzioni dettagliate su come eseguire questa operazione, vedere il seguente collegamento:

Ecco un riepilogo:

  • Vai a Impostazioni Android> Lingue e immissione> Tastiera corrente> Scegli tastiere.
  • Dovresti vedere la tua tastiera personalizzata nell'elenco. Abilitalo.
  • Torna indietro e scegli di nuovo Tastiera corrente. Dovresti vedere la tua tastiera personalizzata nell'elenco. Sceglilo.

Ora dovresti essere in grado di utilizzare la tastiera ovunque tu possa digitare su Android.

Ulteriore studio

La tastiera sopra è utilizzabile, ma per creare una tastiera che altre persone vorranno usare probabilmente dovrai aggiungere più funzionalità. Studia i link sottostanti per scoprire come.

Andando avanti

Non ti piace come KeyboardViewappare e si comporta lo standard ? Io certamente no. Sembra che non sia stato aggiornato da Android 2.0. Che ne dici di tutte quelle tastiere personalizzate nel Play Store? Non assomigliano per niente alla brutta tastiera sopra.

La buona notizia è che puoi personalizzare completamente l'aspetto e il comportamento della tua tastiera. Dovrai fare le seguenti cose:

  1. Crea la tua visualizzazione della tastiera personalizzata che le sottoclassi ViewGroup. Potresti riempirlo con Buttons o persino creare le tue visualizzazioni chiave personalizzate per quella sottoclasse View. Se utilizzi le visualizzazioni popup, prendi nota di questo .
  2. Aggiungi un'interfaccia di listener di eventi personalizzata sulla tastiera. Chiama i suoi metodi per cose come onKeyClicked(String text)o onBackspace().
  3. Non è necessario aggiungere la keyboard_view.xml, key_preview.xmlo number_pad.xmldescritto nelle direzioni sopra dal momento che questi sono tutti per lo standard KeyboardView. Gestirai tutti questi aspetti dell'interfaccia utente nella tua visualizzazione personalizzata.
  4. Nella tua MyInputMethodServiceclasse, implementa il listener di tastiera personalizzato che hai definito nella tua classe di tastiera. Questo è al posto di KeyboardView.OnKeyboardActionListener, che non è più necessario.
  5. Nel metodo MyInputMethodServicedella tua classe onCreateInputView(), crea e restituisci un'istanza della tua tastiera personalizzata. Non dimenticare di impostare l'ascoltatore personalizzato della tastiera su this.

35

Tastiera in-app

Questa risposta spiega come creare una tastiera personalizzata da utilizzare esclusivamente all'interno della tua app. Se vuoi creare una tastiera di sistema che può essere utilizzata in qualsiasi app, guarda la mia altra risposta .

L'esempio sarà simile a questo. Puoi modificarlo per qualsiasi layout di tastiera.

inserisci qui la descrizione dell'immagine

1. Avvia un nuovo progetto Android

Ho chiamato il mio progetto InAppKeyboard. Chiama il tuo come vuoi.

2. Aggiungere i file di layout

Layout della tastiera

Aggiungi un file di layout alla res/layoutcartella. Ho chiamato il mio keyboard. La tastiera sarà una visualizzazione composta personalizzata che gonferemo da questo file di layout xml. Puoi usare il layout che preferisci per disporre i tasti, ma io sto usando un file LinearLayout. Nota i mergetag.

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

A scopo dimostrativo la nostra attività ha un unico EditTexte la tastiera è in basso. Ho chiamato la mia visualizzazione tastiera personalizzata MyKeyboard. (Aggiungeremo presto questo codice, quindi per ora ignoriamo l'errore.) Il vantaggio di mettere tutto il codice della nostra tastiera in un'unica vista è che ne semplifica il riutilizzo in un'altra attività o app.

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. Aggiungere il file Java della tastiera

Aggiungi un nuovo file Java. Ho chiamato il mio MyKeyboard.

La cosa più importante da notare qui è che non esiste alcun collegamento fisico a qualsiasi EditTexto Activity. Ciò semplifica il collegamento a qualsiasi app o attività che ne abbia bisogno. Questa visualizzazione della tastiera personalizzata utilizza anche un InputConnection, che imita il modo in cui una tastiera di sistema comunica con un file EditText. Questo è il modo in cui evitiamo gli hard link.

MyKeyboard è una vista composta che gonfia il layout della vista che abbiamo definito sopra.

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. Puntare la tastiera su EditText

Per le tastiere di sistema, Android usa un InputMethodManager per puntare la tastiera sul focus EditText. In questo esempio, l'attività prenderà il suo posto fornendo il collegamento dalla EditTextalla nostra tastiera personalizzata a.

Dato che non stiamo usando la tastiera di sistema, dobbiamo disabilitarla per evitare che venga visualizzato quando tocchiamo il EditText. Secondo, dobbiamo prendere il InputConnectiondal EditTexte darlo alla nostra tastiera.

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 la tua attività ha più EditText, dovrai scrivere il codice per passare l'EditText corretto InputConnectionalla tastiera. (Puoi farlo aggiungendo un OnFocusChangeListenere OnClickListeneral EditTexts. Vedi questo articolo per una discussione di questo.) Potresti anche voler nascondere o mostrare la tua tastiera nei momenti appropriati.

Finito

Questo è tutto. Dovresti essere in grado di eseguire l'app di esempio ora e inserire o eliminare il testo come desiderato. Il prossimo passo è modificare tutto per adattarlo alle proprie esigenze. Ad esempio, in alcune delle mie tastiere ho utilizzato TextView invece dei pulsanti perché è più facile personalizzarli.

Appunti

  • Nel file di layout xml, potresti anche usare un TextViewpiuttosto a Buttonse vuoi migliorare l'aspetto delle chiavi. Quindi rendi lo sfondo un disegnabile che cambia lo stato dell'aspetto quando viene premuto.
  • Tastiere personalizzate avanzate: per una maggiore flessibilità nell'aspetto della tastiera e nel cambio di tastiera, ora creo visualizzazioni di tasti personalizzate che sottoclasse Viewe tastiere personalizzate che sottoclasse ViewGroup. La tastiera dispone tutti i tasti a livello di programmazione. I tasti utilizzano un'interfaccia per comunicare con la tastiera (simile a come i frammenti comunicano con un'attività). Questo non è necessario se hai bisogno di un solo layout di tastiera poiché il layout xml funziona bene per quello. Ma se vuoi vedere un esempio di ciò su cui ho lavorato, dai un'occhiata a tutte le classi Key*e qui . Nota che utilizzo anche una vista contenitore la cui funzione è di scambiare le tastiere dentro e fuori.Keyboard*

la tua risposta è ottima, ma come possiamo impostare la commutazione tra una tastiera originale e questa nuova tastiera.
Kishan Donga

@KishanDonga, sulla tastiera puoi aggiungere un tasto per cambiare tastiera. Quando l'utente lo preme chiama InputMethodManager#showInputMethodPicker(). Se la tastiera originale non dispone di tale tasto, tuttavia, l'unico modo in cui gli utenti possono passare alla tastiera è farlo manualmente nelle impostazioni di sistema. Apple è superiore ad Android in quest'area, perché Apple richiede che tutte le tastiere abbiano un tasto per cambiare tastiera.
Suragch

@KishanDonga, mi sono appena reso conto che questa risposta riguarda una tastiera in-app, non la tastiera di sistema. Se desideri scambiare tra due tastiere personalizzate, puoi scambiarle a livello di codice dentro e fuori una visualizzazione contenitore. Basta aggiungere un tasto di scambio delle tastiere su entrambe le tastiere. Vedere la mia nota "tastiere personalizzate avanzate" e il collegamento nella risposta sopra.
Suragch

Se vuoi passare dalla tastiera alla tastiera di sistema, nascondi la tastiera di sistema e mostra la tastiera nei momenti appropriati (e viceversa).
Suragch

1
@MarekTakac, dovrai disabilitare la tastiera di sistema e aggiungere la tua tastiera personalizzata in ogni attività. Se un'attività ha più messaggi EditText, sarà necessario aggiungerne uno onFocusChangedListenerin modo che quando ricevono il focus puoi assegnare il InputConnectiondalla corrente EditTextalla tua tastiera personalizzata.
Suragch

31

Usa KeyboardView:

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

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

ora hai kbduna visualizzazione normale.

La cosa bella di questo è che R.xml.customfa riferimento a /res/xml/custom.xml, che definisce in xml il layout della tastiera. Per ulteriori informazioni su questo file, guarda qui: Keyboard , Keyboard.Row , Keyboard.Key .


2
Sto usando la classe KeyboardView, ma a partire dall'API 29, ora è deprecata.
Abhijit

14

Ecco un progetto di esempio per una tastiera morbida.

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

I tuoi dovrebbero essere nelle stesse linee con un layout diverso.

Modifica: se hai bisogno della tastiera solo nella tua applicazione, è molto semplice! Crea un layout lineare con orientamento verticale e crea 3 layout lineari al suo interno con orientamento orizzontale. Quindi posizionare i pulsanti di ciascuna riga in ciascuno di questi layout lineari orizzontali e assegnare la proprietà del peso ai pulsanti. Usa android: layout_weight = 1 per tutti, in modo che siano equidistanti.

Questo risolverà. Se non hai ottenuto ciò che ti aspettavi, inserisci il codice qui e noi siamo qui per aiutarti!


La modifica è effettivamente pessima perché ciò significherebbe che la tastiera viene sempre visualizzata e non si comporterà come la tastiera Android di serie.
m0skit0


4

Mi sono imbattuto in questo post di recente quando stavo cercando di decidere quale metodo utilizzare per creare la mia tastiera personalizzata. Ho trovato l'API del sistema Android molto limitata, quindi ho deciso di creare la mia tastiera in-app. Utilizzando la risposta di Suragch come base per la mia ricerca, ho continuato a progettare il mio componente di tastiera . È pubblicato su GitHub con una licenza MIT. Si spera che questo farà risparmiare a qualcun altro molto tempo e mal di testa.

L'architettura è piuttosto flessibile. C'è una vista principale (CustomKeyboardView) che puoi inserire con qualsiasi layout di tastiera e controller desideri.

Devi solo dichiarare CustomKeyboardView nella tua attività xml (puoi farlo anche a livello di programmazione):

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

Quindi registra il tuo EditText con esso e digli quale tipo di tastiera dovrebbero usare:

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 gestisce il resto!

Ho la palla che rotola con una tastiera Number, NumberDecimal e QWERTY. Sentiti libero di scaricarlo e creare i tuoi layout e controller. Assomiglia a questo:

paesaggio gif della tastiera personalizzata Android

inserisci qui la descrizione dell'immagine

Anche se questa non è l'architettura con cui decidi di utilizzare, si spera che sia utile vedere il codice sorgente per una tastiera in-app funzionante.

Di nuovo, ecco il collegamento al progetto: Tastiera in-app personalizzata


2

Bene, Suragch ha dato la risposta migliore finora, ma ha saltato alcune cose minori che erano importanti per compilare l'app.

Spero di dare una risposta migliore di Suragch migliorando la sua risposta. Aggiungerò tutti gli elementi mancanti che non ha inserito.

Ho compilato il mio apk utilizzando l'app Android, APK Builder 1.1.0. Quindi iniziamo.

Per costruire un'app Android abbiamo bisogno di un paio di file e cartelle organizzati in un certo formato e capitalizzati di conseguenza.

res layout -> file xml che raffigurano l'aspetto dell'app sul telefono. Simile a come html modella l'aspetto della pagina web sul browser. Consentire alla tua app di adattarsi agli schermi di conseguenza.

valori -> dati costanti come colors.xml, strings.xml, styles.xml. Questi file devono essere scritti correttamente.

drawable -> pics {jpeg, png, ...}; Dai loro un nome qualsiasi.

mipmap -> altre foto. utilizzato per l'icona dell'app?

xml -> più file xml.

src -> agisce come JavaScript in html. i file di layout avvieranno la visualizzazione iniziale e il file java controllerà dinamicamente gli elementi dei tag e attiverà gli eventi. Gli eventi possono anche essere attivati ​​direttamente nel layout.xml proprio come in html.

AndroidManifest.xml -> Questo file registra di cosa tratta la tua app. Nome dell'applicazione, tipo di programma, autorizzazioni necessarie, ecc. Questo sembra rendere Android piuttosto sicuro. I programmi letteralmente non possono fare ciò che non chiedevano nel Manifest.

Ora ci sono 4 tipi di programmi Android, un'attività, un servizio, un fornitore di contenuti e un ricevitore di trasmissione. La nostra tastiera sarà un servizio che gli consentirà di funzionare in background. Non apparirà nell'elenco delle app da avviare; ma può essere disinstallato.

Per compilare la tua app, sono necessari gradle e firma apk. Puoi ricercarlo o utilizzare APK Builder per Android. È semplicissimo.

Ora che comprendiamo lo sviluppo di Android, creiamo i file e le cartelle.

  1. Crea i file e le cartelle come ho discusso sopra. La mia directory apparirà come segue:

    • NumPad
      • AndroidManifest.xml
      • src
        • Saragch
          • NUM_PAD
            • MyInputMethodService.java
      • res
        • drawable
          • Suragch_NumPad_icon.png
        • disposizione
          • key_preview.xml
          • keyboard_view.xml
        • xml
          • method.xml
          • number_pad.xml
        • valori
          • colors.xml
          • strings.xml
          • styles.xml

Ricorda che se stai usando un ide come Android Studio potrebbe avere un file di progetto.

  1. Scrivi file.

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: Numpad / 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>

Ovviamente questo può essere facilmente modificato a proprio piacimento. Puoi anche usare immagini invece di parole per l'etichetta.

Suragch non ha dimostrato i file nella cartella dei valori e ha supposto che avessimo accesso ad Android Studio; che li crea automaticamente. Per fortuna ho 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: tastierino numerico / AndroidManifest.xml

Questo è il file che era davvero in discussione. Qui ho sentito che non avrei mai compilato il mio programma. singhiozzare. singhiozzare. Se controlli la risposta di Suracgh, vedrai che lascia il primo gruppo di campi vuoto e aggiunge il tag attività in questo file. Come ho detto, esistono quattro tipi di programmi Android. Un'attività è un'app normale con un'icona di avvio. Questo tastierino numerico non è un'attività! Inoltre non ha implementato alcuna attività.

I miei amici non includono il tag attività. Il tuo programma verrà compilato e quando proverai ad avviarlo andrà in crash! Per quanto riguarda xmlns: android e uses-sdk; Non posso aiutarti. Prova le mie impostazioni se funzionano.

Come puoi vedere c'è un codice di matricola, che lo registra come servizio. Anche service.android:name deve essere il nome della classe pubblica che estende il servizio nel nostro file java. DEVE essere capitalizzato di conseguenza. Inoltre pacchetto è il nome del pacchetto che abbiamo dichiarato nel file 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

Nota: penso che java sia un'alternativa a src.

Questo era un altro file problematico ma non così controverso come il file manifest. Dato che conosco Java abbastanza bene da sapere cosa è cosa e cosa non lo è. Conosco a malapena XML e come si lega allo sviluppo di Android!

Il problema qui era che non importava nulla! Voglio dire, ci ha fornito un file "completo" che utilizza nomi che non possono essere risolti! InputMethodService, Keyboard, ecc. Questa è una cattiva pratica, signor Suragch. Grazie per avermi aiutato, ma come ti aspettavi la compilazione del codice se i nomi non possono essere risolti?

Di seguito è riportata la versione modificata correttamente. Mi è capitato di cogliere un paio di suggerimenti per portarmi nel posto giusto per imparare cosa esattamente importare.

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 e firma il tuo progetto.

    È qui che non ho idea come sviluppatore Android. Mi piacerebbe impararlo manualmente, poiché credo che i veri programmatori possano compilare manualmente.

Penso che gradle sia uno degli strumenti per la compilazione e il packaging in apk. apk sembra essere come un file jar o un rar per file zip. Esistono quindi due tipi di firma. chiave di debug che non è consentita su Play Store e chiave privata.

Bene, diamo una mano al signor Saragch. E grazie per aver guardato il mio video. Mi piace, iscriviti.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.