Comment créer un clavier personnalisé sous Android?

105

Je souhaite créer un clavier personnalisé. Je ne sais pas comment le faire en utilisant XML et Java. L'image suivante est un modèle du clavier que je souhaite créer. Il n'a besoin que de chiffres.

entrez la description de l'image ici

XX_brother
la source
6
[Créez votre propre clavier personnalisé à l'aide de dispositions XML pour les appareils Android] ( tutoriels-android.blogspot.com/2011/06/… )
Jorgesys
1
Il y a un bon tutoriel chez Tuts: lien
Hamed Ghadirian
Google a un exemple de projet "SoftKeyboard", ou il y a pas mal de ressources liées ici: customkeyboarddetails.blogspot.com/2019/02
...

Réponses:

83

Tout d'abord, vous aurez besoin d'un keyboard.xmlfichier qui sera placé dans le res/xmldossier (si le dossier n'existe pas, créez-le).

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

** Notez que vous devrez créer le backspacedessinable et le placer dans le dossier res / drawable-ldpi avec une très petite taille (comme 18x18 pixels)

Ensuite, dans le fichier xml que vous souhaitez qu'il soit utilisé (où se trouve votre TextView), vous devez ajouter le code suivant:

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

** Notez que le fichier xml dans lequel vous allez placer le android.inputmethodservice.KeyboardViewdoit être RelativeLayoutpour pouvoir définir le alignParentBottom="true"(Habituellement, les claviers sont présentés en bas de l'écran)

Ensuite, vous devez ajouter le code suivant dans la onCreatefonction du Activityqui gère le auquel TextViewvous souhaitez attacher le clavier

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

** Notez que mKeyboardet mKeyboardViewsont des variables de classe privées que vous devez créer.

Ensuite, vous avez besoin de la fonction suivante pour ouvrir le clavier (vous devez l'associer au TextView via la onClickpropriété 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);
    }

Et enfin vous avez besoin du OnKeyboardActionListenerqui gérera vos événements

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

J'espère que cela pourra aider!!!

La plupart du code trouvé ici

Pontios
la source
1
Que faire si je ne veux pas que le clavier soit en bas de l'écran? (par exemple, je veux que l'utilisateur puisse le faire glisser). Est-ce quelque chose que je peux contrôler via mon application clavier ou est-il géré par le système Android?
user3294126
la largeur du clavier ne remplit pas l'écran que dois-je faire pour qu'il remplisse tous les écrans
George Thomas
Quelle est la disposition parente dans laquelle se trouve KeyboardView? Avez-vous également vérifié le layout_width de KeyboardView ??
Pontios
1
Veuillez noter que les classes KeyboardView et Keyboard sont obsolètes par Google depuis le niveau d'API 29. Cette solution ne fonctionnera donc plus à l'avenir si vous devez cibler un niveau d'API plus récent.
maex
keyboardView est obsolète par google. quelle est la nouvelle solution?
tohidmahmoudvand le
78

Clavier système

Cette réponse explique comment créer un clavier système personnalisé qui peut être utilisé dans n'importe quelle application qu'un utilisateur a installée sur son téléphone. Si vous souhaitez créer un clavier qui ne sera utilisé que dans votre propre application, consultez mon autre réponse .

L'exemple ci-dessous ressemblera à ceci. Vous pouvez le modifier pour n'importe quelle disposition de clavier.

entrez la description de l'image ici

Les étapes suivantes montrent comment créer un clavier système personnalisé fonctionnel. Autant que possible, j'ai essayé de supprimer tout code inutile. Si vous avez besoin d'autres fonctionnalités, j'ai fourni des liens vers une aide supplémentaire à la fin.

1. Démarrez un nouveau projet Android

J'ai nommé mon projet "Clavier personnalisé". Appelez ça comme vous voulez. Il n'y a rien d'autre de spécial ici. Je vais juste quitter le MainActivityet "Hello World!" mise en page telle qu'elle est.

2. Ajoutez les fichiers de mise en page

Ajoutez les deux fichiers suivants au dossier de votre application res/layout:

  • keyboard_view.xml
  • key_preview.xml

keyboard_view.xml

Cette vue est comme un conteneur qui contiendra notre clavier. Dans cet exemple, il n'y a qu'un seul clavier, mais vous pouvez ajouter d'autres claviers et les échanger entre eux 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'aperçu des touches est une mise en page qui apparaît lorsque vous appuyez sur une touche du clavier. Il montre simplement sur quelle touche vous appuyez (au cas où vos gros doigts la recouvriraient). Ce n'est pas une fenêtre contextuelle à choix multiples. Pour cela, vous devriez consulter la vue Candidats .

<?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. Ajouter des fichiers xml de prise en charge

Créez un xmldossier dans votre resdossier. (Cliquez avec le bouton droit reset choisissez Nouveau> Répertoire .)

Ajoutez-y ensuite les deux fichiers xml suivants. (Cliquez avec le bouton droit sur le xmldossier et choisissez Nouveau> Fichier de ressources XML .)

  • number_pad.xml
  • method.xml

number_pad.xml

C'est là que ça commence à devenir plus intéressant. Ceci Keyboarddéfinit la disposition des touches .

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

Voici quelques points à noter:

  • keyWidth: Il s'agit de la largeur par défaut de chaque clé. Les 20%pmoyens que chaque clé doit prendre 20% de la largeur de la p arent. Cependant, il peut être remplacé par des touches individuelles, comme vous pouvez le voir avec les touches Supprimer et Entrée de la troisième ligne.
  • keyHeight: Il est codé en dur ici, mais vous pouvez utiliser quelque chose comme @dimen/key_heightpour le définir dynamiquement pour différentes tailles d'écran.
  • Gap: L'espace horizontal et vertical indique l'espace à laisser entre les touches. Même si vous le réglez, il 0pxy a encore un petit écart.
  • codes: Il peut s'agir d'une valeur Unicode ou de code personnalisé qui détermine ce qui se passe ou ce qui est entré lorsque la touche est enfoncée. Voyez keyOutputTextsi vous souhaitez saisir une chaîne Unicode plus longue.
  • keyLabel: Il s'agit du texte affiché sur la clé.
  • keyEdgeFlags: Ceci indique sur quel bord la touche doit être alignée.
  • isRepeatable: Si vous maintenez la touche enfoncée, il continuera à répéter l'entrée.

method.xml

Ce fichier indique au système les sous-types de méthode d'entrée disponibles. J'inclus juste une version minimale ici.

<?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. Ajoutez le code Java pour gérer l'entrée de clé

Créez un nouveau fichier Java. Appelons ça MyInputMethodService. Ce fichier lie tout ensemble. Il gère les entrées reçues du clavier et les envoie à la vue qui la reçoit (un EditText, par exemple).

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

Remarques:

  • L' OnKeyboardActionListenerécoute pour la saisie au clavier. Cela nécessite également toutes ces méthodes vides dans cet exemple.
  • Le InputConnectionest ce qui est utilisé pour envoyer une entrée à une autre vue comme un EditText.

5. Mettez à jour le manifeste

Je mets ce dernier plutôt que le premier car il fait référence aux fichiers que nous avons déjà ajoutés ci-dessus. Pour enregistrer votre clavier personnalisé en tant que clavier système, vous devez ajouter une servicesection à votre fichier AndroidManifest.xml . Mettez-le dans la applicationsection après 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>

C'est tout! Vous devriez pouvoir exécuter votre application maintenant. Cependant, vous ne verrez pas grand-chose tant que vous n'aurez pas activé votre clavier dans les paramètres.

6. Activez le clavier dans les paramètres

Chaque utilisateur souhaitant utiliser votre clavier devra l'activer dans les paramètres Android. Pour obtenir des instructions détaillées sur la façon de procéder, consultez le lien suivant:

Voici un résumé:

  • Accédez à Paramètres Android> Langues et saisie> Clavier actuel> Choisir les claviers.
  • Vous devriez voir votre clavier personnalisé dans la liste. Activez-le.
  • Revenez en arrière et choisissez à nouveau Clavier actuel. Vous devriez voir votre clavier personnalisé dans la liste. Choisis le.

Vous devriez maintenant pouvoir utiliser votre clavier partout où vous pouvez taper dans Android.

Une étude plus approfondie

Le clavier ci-dessus est utilisable, mais pour créer un clavier que d'autres personnes voudront utiliser, vous devrez probablement ajouter plus de fonctionnalités. Étudiez les liens ci-dessous pour savoir comment.

Continuer

Vous n'aimez pas l' KeyboardViewapparence et le comportement de la norme ? Certainement pas moi. Il semble qu'il n'a pas été mis à jour depuis Android 2.0. Que diriez-vous de tous ces claviers personnalisés dans le Play Store? Ils ne ressemblent en rien au vilain clavier ci-dessus.

La bonne nouvelle est que vous pouvez personnaliser complètement l'apparence et le comportement de votre propre clavier. Vous devrez faire les choses suivantes:

  1. Créez votre propre vue de clavier personnalisée qui les sous-classes ViewGroup. Vous pouvez le remplir de Buttons ou même créer vos propres vues clés personnalisées pour cette sous-classe View. Si vous utilisez des vues contextuelles, notez ceci .
  2. Ajoutez une interface d' écoute d'événement personnalisée dans votre clavier. Appelez ses méthodes pour des choses comme onKeyClicked(String text)ou onBackspace().
  3. Vous n'avez pas besoin d'ajouter le keyboard_view.xml, key_preview.xmlou number_pad.xmldécrit dans les instructions ci-dessus car ils sont tous pour la norme KeyboardView. Vous gérerez tous ces aspects de l'interface utilisateur dans votre vue personnalisée.
  4. Dans votre MyInputMethodServiceclasse, implémentez l'écouteur de clavier personnalisé que vous avez défini dans votre classe de clavier. C'est à la place de KeyboardView.OnKeyboardActionListener, qui n'est plus nécessaire.
  5. Dans MyInputMethodServicela onCreateInputView()méthode de votre classe , créez et renvoyez une instance de votre clavier personnalisé. N'oubliez pas de définir l'écouteur personnalisé du clavier sur this.
Suragch
la source
35

Clavier intégré à l'application

Cette réponse explique comment créer un clavier personnalisé à utiliser exclusivement dans votre application. Si vous souhaitez créer un clavier système pouvant être utilisé dans n'importe quelle application, consultez mon autre réponse .

L'exemple ressemblera à ceci. Vous pouvez le modifier pour n'importe quelle disposition de clavier.

entrez la description de l'image ici

1. Démarrez un nouveau projet Android

J'ai nommé mon projet InAppKeyboard. Appelez le vôtre comme vous voulez.

2. Ajoutez les fichiers de mise en page

Clavier

Ajoutez un fichier de mise en page au res/layoutdossier. J'ai appelé le mien keyboard. Le clavier sera une vue composée personnalisée que nous gonflerons à partir de ce fichier de disposition xml. Vous pouvez utiliser la disposition de votre choix pour organiser les touches, mais j'utilise un fichier LinearLayout. Notez les mergebalises.

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>

Disposition des activités

À des fins de démonstration, notre activité a un seul EditTextet le clavier est en bas. J'ai appelé ma vue clavier personnalisée MyKeyboard. (Nous ajouterons bientôt ce code, alors ignorez l'erreur pour le moment.) L'avantage de mettre tout notre code de clavier dans une seule vue est qu'il est facile à réutiliser dans une autre activité ou application.

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. Ajoutez le fichier Java Keyboard

Ajoutez un nouveau fichier Java. J'ai appelé le mien MyKeyboard.

La chose la plus importante à noter ici est qu'il n'y a pas de lien direct vers l'un EditTextou l'autre Activity. Cela permet de le connecter facilement à toute application ou activité qui en a besoin. Cette vue du clavier personnalisé utilise également un InputConnection, qui imite la façon dont un clavier système communique avec un EditText. C'est ainsi que nous évitons les liens durs.

MyKeyboard est une vue composée qui gonfle la disposition de vue définie ci-dessus.

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. Pointez le clavier sur EditText

Pour les claviers système, Android utilise un InputMethodManager pour pointer le clavier vers le focus EditText. Dans cet exemple, l'activité prendra sa place en fournissant le lien du EditTextvers notre clavier personnalisé vers.

Puisque nous n'utilisons pas le clavier système, nous devons le désactiver pour l'empêcher d'apparaître lorsque nous touchons le EditText. Deuxièmement, nous devons obtenir le InputConnectiondepuis le EditTextet le donner à notre clavier.

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 votre activité comporte plusieurs EditTexts, vous devrez écrire du code pour transmettre les bons EditText InputConnectionau clavier. (Vous pouvez le faire en ajoutant un OnFocusChangeListeneret OnClickListeneraux EditTexts. Consultez cet article pour une discussion à ce sujet.) Vous pouvez également masquer ou afficher votre clavier à des moments appropriés.

Fini

C'est tout. Vous devriez pouvoir exécuter l'exemple d'application maintenant et saisir ou supprimer du texte comme vous le souhaitez. Votre prochaine étape consiste à tout modifier pour répondre à vos propres besoins. Par exemple, sur certains de mes claviers, j'ai utilisé TextViews plutôt que Buttons car il est plus facile de les personnaliser.

Remarques

  • Dans le fichier de mise en page xml, vous pouvez également utiliser un TextViewplutôt a Buttonsi vous souhaitez améliorer l'apparence des touches. Ensuite, faites simplement de l'arrière-plan un dessin qui change l'état d'apparence lorsque vous appuyez sur.
  • Claviers personnalisés avancés: pour plus de flexibilité dans l'apparence du clavier et le changement de clavier, je crée maintenant des vues de touches personnalisées qui sous-classe Viewet des claviers personnalisés qui sous-classe ViewGroup. Le clavier dispose toutes les touches par programme. Les touches utilisent une interface pour communiquer avec le clavier (similaire à la façon dont les fragments communiquent avec une activité). Ce n'est pas nécessaire si vous n'avez besoin que d'une seule disposition de clavier car la disposition xml fonctionne bien pour cela. Mais si vous voulez voir un exemple de ce sur quoi j'ai travaillé, consultez toutes les classes Key*et ici . Notez que j'utilise également une vue conteneur là-bas dont la fonction est de permuter les claviers vers l'intérieur et l'extérieur.Keyboard*
Suragch
la source
votre réponse est excellente, mais comment pouvons-nous basculer entre un clavier d'origine et ce nouveau clavier.
Kishan Donga
@KishanDonga, Sur votre clavier, vous pouvez ajouter une touche pour changer de clavier. Lorsque l'utilisateur appuie sur il appelle InputMethodManager#showInputMethodPicker(). Si le clavier d'origine ne dispose pas d'une telle touche, la seule façon pour les utilisateurs de passer à votre clavier est de le faire manuellement dans les paramètres système. Apple est supérieur à Android dans ce domaine, car Apple exige que tous les claviers aient une touche de commutation de clavier.
Suragch
@KishanDonga, je viens de réaliser que cette réponse concerne un clavier intégré à l'application, pas le clavier système. Si vous souhaitez permuter entre deux claviers personnalisés, vous pouvez les échanger par programmation dans et hors d'une vue de conteneur. Ajoutez simplement une clé de clavier d'échange sur les deux claviers. Voir ma note et mon lien "Claviers personnalisés avancés" dans la réponse ci-dessus.
Suragch
Si vous souhaitez basculer entre votre clavier et le clavier système, masquez le clavier système et affichez votre clavier aux moments appropriés (et vice versa).
Suragch
1
@MarekTakac, vous devrez désactiver le clavier système et ajouter votre clavier personnalisé dans chaque activité. Si une activité comporte plusieurs EditTexts, vous devrez leur ajouter un onFocusChangedListenerafin que, lorsqu'ils reçoivent le focus, vous puissiez attribuer le InputConnectiondu courant EditTextà votre clavier personnalisé.
Suragch le
31

Utilisez KeyboardView:

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

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

maintenant vous avez kbdce qui est une vue normale.

La bonne chose à ce sujet est que se R.xml.customréfère à /res/xml/custom.xml, qui définit en XML la disposition du clavier. Pour plus d'informations sur ce fichier, regardez ici: Keyboard , Keyboard.Row , Keyboard.Key .

grosses pierres
la source
2
J'utilise la classe KeyboardView, mais à partir de l'API 29, elle est désormais obsolète.
Abhijit
14

Voici un exemple de projet pour un clavier logiciel.

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

Le vôtre doit être dans les mêmes lignes avec une disposition différente.

Edit: Si vous n'avez besoin du clavier que dans votre application, c'est très simple! Créez une mise en page linéaire avec une orientation verticale et créez 3 mises en page linéaires à l'intérieur avec une orientation horizontale. Placez ensuite les boutons de chaque ligne dans chacune de ces dispositions linéaires horizontales et attribuez la propriété weight aux boutons. Utilisez android: layout_weight = 1 pour tous, afin qu'ils soient également espacés.

Cela résoudra. Si vous n'avez pas obtenu ce que vous attendiez, veuillez poster le code ici, et nous sommes là pour vous aider!

nithinreddy
la source
La modification est en fait mauvaise car cela signifierait que le clavier est toujours affiché et ne se comportera pas comme un clavier Android d'origine.
m0skit0 le
4

Je suis tombé sur ce post récemment lorsque j'essayais de décider de la méthode à utiliser pour créer mon propre clavier personnalisé. J'ai trouvé que l'API du système Android était très limitée, j'ai donc décidé de créer mon propre clavier intégré à l'application. En utilisant la réponse de Suragch comme base de mes recherches, j'ai continué à concevoir mon propre composant de clavier . Il est publié sur GitHub avec une licence MIT. J'espère que cela permettra à quelqu'un d'économiser beaucoup de temps et de maux de tête.

L'architecture est assez flexible. Il existe une vue principale (CustomKeyboardView) que vous pouvez injecter avec la disposition de clavier et le contrôleur de votre choix.

Il vous suffit de déclarer le CustomKeyboardView dans votre activité xml (vous pouvez également le faire par programme):

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

Enregistrez ensuite votre EditText avec lui et indiquez-lui le type de clavier à utiliser:

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

Le CustomKeyboardView gère le reste!

J'ai le bal avec un clavier Number, NumberDecimal et QWERTY. N'hésitez pas à le télécharger et à créer vos propres mises en page et contrôleurs. Cela ressemble à ceci:

paysage gif clavier personnalisé android

entrez la description de l'image ici

Même si ce n'est pas l'architecture que vous décidez d'utiliser, j'espère qu'il sera utile de voir le code source d'un clavier intégré à l'application.

Encore une fois, voici le lien vers le projet: Clavier In-App personnalisé

Don Brody
la source
2

Eh bien, Suragch a donné la meilleure réponse jusqu'à présent, mais il a sauté certaines choses mineures qui étaient importantes pour la compilation de l'application.

J'espère apporter une meilleure réponse que Suragch en améliorant sa réponse. J'ajouterai tous les éléments manquants qu'il n'a pas mis.

J'ai compilé mon apk en utilisant l'application Android, APK Builder 1.1.0. Alors commençons.

Pour créer une application Android, nous avons besoin de quelques fichiers et dossiers organisés dans un certain format et mis en majuscules en conséquence.

res layout -> fichiers xml illustrant l'apparence de l'application sur le téléphone. Similaire à la façon dont le HTML façonne l'apparence de la page Web sur le navigateur. Permettre à votre application de s'adapter aux écrans en conséquence.

valeurs -> données constantes telles que colors.xml, strings.xml, styles.xml. Ces fichiers doivent être correctement orthographiés.

dessinable -> pics {jpeg, png, ...}; Nommez-les n'importe quoi.

mipmap -> plus de photos. utilisé pour l'icône de l'application?

xml -> plus de fichiers xml.

src -> agit comme JavaScript en html. Les fichiers de mise en page lanceront la vue de départ et votre fichier java contrôlera dynamiquement les éléments de balise et déclenchera des événements. Les événements peuvent également être activés directement dans le layout.xml tout comme en html.

AndroidManifest.xml -> Ce fichier enregistre l'objet de votre application. Nom de l'application, type de programme, autorisations nécessaires, etc. Cela semble rendre Android plutôt sûr. Les programmes ne peuvent littéralement pas faire ce qu'ils n'ont pas demandé dans le manifeste.

Il existe désormais 4 types de programmes Android, une activité, un service, un fournisseur de contenu et un récepteur de diffusion. Notre clavier sera un service, ce qui lui permettra de fonctionner en arrière-plan. Il n'apparaîtra pas dans la liste des applications à lancer; mais il peut être désinstallé.

Pour compiler votre application, implique la signature gradle et apk. Vous pouvez rechercher celui-ci ou utiliser APK Builder pour Android. C'est super facile.

Maintenant que nous comprenons le développement Android, créons les fichiers et les dossiers.

  1. Créez les fichiers et les dossiers comme indiqué ci-dessus. Mon répertoire ressemblera à ceci:

    • Pavé numérique
      • AndroidManifest.xml
      • src
        • Saragch
          • pavé numérique
            • MyInputMethodService.java
      • res
        • dessinable
          • Suragch_NumPad_icon.png
        • disposition
          • key_preview.xml
          • keyboard_view.xml
        • xml
          • method.xml
          • number_pad.xml
        • valeurs
          • colors.xml
          • strings.xml
          • styles.xml

N'oubliez pas que si vous utilisez un ide tel qu'Android Studio, il peut avoir un fichier projet.

  1. Écrivez des fichiers.

A: Pavnum / 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: Pavé numérique / 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>

Bien sûr, cela peut être facilement modifié à votre goût. Vous pouvez même utiliser des images à la place des mots pour l'étiquette.

Suragch n'a pas montré les fichiers dans le dossier des valeurs et a supposé que nous avions accès à Android Studio; qui les crée automatiquement. Heureusement que j'ai 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: Pavé numérique / AndroidManifest.xml

C'est le dossier qui était vraiment à l'ordre du jour. Ici, j'ai senti que je ne compilerais jamais mon programme. sanglot. sanglot. Si vous cochez la réponse de Suracgh, vous voyez qu'il laisse le premier ensemble de champs vide et ajoute la balise d'activité dans ce fichier. Comme je l'ai dit, il existe quatre types de programmes Android. Une activité est une application classique avec une icône de lanceur. Ce pavé numérique n'est pas une activité! De plus, il n'a mis en œuvre aucune activité.

Mes amis n'incluent pas le tag d'activité. Votre programme se compilera et lorsque vous essayez de le lancer, il plantera! Quant à xmlns: android et uses-sdk; Je ne peux pas vous aider. Essayez simplement mes paramètres s'ils fonctionnent.

Comme vous pouvez le voir, il existe une étiquette de service qui l'enregistre en tant que service. De plus, service.android:name doit être le nom du service d'extension de classe publique dans notre fichier java. Il DOIT être capitalisé en conséquence. Package est également le nom du package que nous avons déclaré dans le fichier 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: Pavnum / src / Saragch / pavé numérique / MyInputMethodService.java

Remarque: je pense que java est une alternative à src.

C'était un autre fichier problématique mais pas aussi controversé que le fichier manifeste. Comme je connais Java assez bien pour savoir ce qui est quoi, ce qui ne l'est pas. Je connais à peine xml et comment il est lié au développement Android!

Le problème ici était qu'il n'avait rien importé! Je veux dire, il nous a donné un fichier "complet" qui utilise des noms qui n'ont pas pu être résolus! InputMethodService, Keyboard, etc. C'est une mauvaise pratique M. Suragch. Merci de m'avoir aidé, mais comment vous attendiez-vous à ce que le code se compile si les noms ne peuvent pas être résolus?

Voici la version correctement modifiée. Il m'est arrivé de sauter sur quelques indices pour me conduire au bon endroit pour savoir exactement quoi importer.

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. Compilez et signez votre projet.

    C'est là que je n'ai aucune idée en tant que nouveau développeur Android. J'aimerais l'apprendre manuellement, car je pense que les vrais programmeurs peuvent compiler manuellement.

Je pense que gradle est l'un des outils de compilation et d'empaquetage sur apk. apk ressemble à un fichier jar ou à un rar pour un fichier zip. Il existe alors deux types de signature. clé de débogage qui n'est pas autorisée sur le Play Store et la clé privée.

Eh bien, donnons un coup de main à M. Saragch. Et merci d'avoir regardé ma vidéo. Comme, abonnez-vous.

marc_s
la source