Android Custom Keyboard Layout Tutorial

In this tutorial learn how to build your own Android Custom Keyboard layout using Android Studio by writing few lines of code. Here is a preview of the custom keyboard layout we are going to build today:

android custom keyboard layout

The Keyboard follow Google’s Android Material Design Guidelines.

Android Custom Keyboard Layout

Getting Started

Open Android Studio and create an empty project with No activity.

Creating Layout

Once the project build is finished, first go to colors.xml and set color theme for your keyboard with following name attributes:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>

    <!--Color your keyboard-->
    <color name="keyboard_background_color">#008577</color>
    <color name="keyboard_divider">#00574B</color>
    <color name="keyboard_pressed">#D81B60</color>
</resources>

Now in res folder, create an Android Resource directory with name ‘xml‘ inside this directory create a xml file with name method.xml. In this file we will set the default language for our keyboard layout.

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

    <subtype
        android:label="English (US)"
        android:imeSubtypeLocale="en_US"
        android:imeSubtypeMode="keyboard"/>

</input-method>

Now, we will create the layout for our Android Custom keyboard as shown in the image above. Go to xml directory and create a new xml resource file with name ‘qwerty.xml

Create the layout of your custom keyboard as follows:

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

    <Row>

        <Key android:keyLabel="1"
            android:keyEdgeFlags="left"
            android:codes="49"/>

        <Key android:keyLabel="2"
            android:codes="50"/>

        <Key android:keyLabel="3"
            android:codes="51"/>

        <Key android:keyLabel="4"
            android:codes="52"/>

        <Key android:keyLabel="5"
            android:codes="53"/>

        <Key android:keyLabel="6"
            android:codes="54"/>

        <Key android:keyLabel="7"
            android:codes="55"/>

        <Key android:keyLabel="8"
            android:codes="56"/>

        <Key android:keyLabel="9"
            android:codes="57"/>

        <Key android:keyLabel="0"
            android:keyEdgeFlags="right"
            android:codes="48"/>

    </Row>

    <Row>

        <Key android:keyLabel="q"
            android:keyEdgeFlags="left"
            android:codes="113"/>

        <Key android:keyLabel="w"
            android:codes="119"/>

        <Key android:keyLabel="e"
            android:codes="101"/>

        <Key android:keyLabel="r"
            android:codes="114"/>

        <Key android:keyLabel="t"
            android:codes="116"/>

        <Key android:keyLabel="y"
            android:codes="121"/>

        <Key android:keyLabel="u"
            android:codes="117"/>

        <Key android:keyLabel="i"
            android:codes="105"/>

        <Key android:keyLabel="o"
            android:codes="111"/>

        <Key android:keyLabel="p"
            android:keyEdgeFlags="right"
            android:codes="112"/>

    </Row>

    <Row>

        <Key android:keyLabel="a"
            android:keyEdgeFlags="left"
            android:codes="97"/>

        <Key android:keyLabel="s"
            android:codes="115"/>

        <Key android:keyLabel="d"
            android:codes="100"/>

        <Key android:keyLabel="f"
            android:codes="102"/>

        <Key android:keyLabel="g"
            android:codes="103"/>

        <Key android:keyLabel="h"
            android:codes="104"/>

        <Key android:keyLabel="j"
            android:codes="106"/>

        <Key android:keyLabel="k"
            android:codes="107"/>

        <Key android:keyLabel="l"
            android:codes="108"/>

        <Key android:keyLabel="\# \@"
            android:keyEdgeFlags="right"
            android:codes="35,67"/>

    </Row>

    <Row>

        <Key android:keyLabel="CAPS"
            android:keyEdgeFlags="left"
            android:codes="-1"/>

        <Key android:keyLabel="z"
            android:codes="122"/>

        <Key android:keyLabel="x"
            android:codes="120"/>

        <Key android:keyLabel="c"
            android:codes="99"/>

        <Key android:keyLabel="v"
            android:codes="118"/>

        <Key android:keyLabel="b"
            android:codes="98"/>

        <Key android:keyLabel="n"
            android:codes="110"/>

        <Key android:keyLabel="m"
            android:codes="109"/>

        <Key android:keyLabel="."
            android:codes="46"/>

        <Key android:keyLabel="\? ! :"
            android:keyEdgeFlags="right"
            android:codes="63,33,58"/>

    </Row>


    <Row android:rowEdgeFlags="bottom">

        <Key android:keyLabel=","
            android:keyWidth="10%p"
            android:keyEdgeFlags="left"
            android:codes="44"/>

        <Key android:keyLabel="/"
            android:keyWidth="10%p"
            android:codes="47"/>

        <Key android:keyLabel="SPACE"
            android:keyWidth="40%p"
            android:isRepeatable="true"
            android:codes="32"/>

        <Key android:keyLabel="DEL"
            android:keyWidth="20%p"
            android:isRepeatable="true"
            android:codes="-5"/>

        <Key android:keyLabel="ENTR"
            android:keyWidth="20%p"
            android:keyEdgeFlags="right"
            android:codes="-4"/>

    </Row>

</Keyboard>

Now go to res folder and create a new android layout resource folder, with name ‘layout‘. In this layout folder create a layout resource file with name ‘keyboard.xml

Inside keyboard.xml we will create the KeyboardView and set its layout attributes. The code for keyboardView is as follows:

<?xml version="1.0" encoding="utf-8"?>

<android.inputmethodservice.KeyboardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_alignParentBottom="true"

    android:keyTextColor="@android:color/white"
    android:keyBackground="@drawable/key_background"
    android:keyPreviewLayout="@layout/key_preview"
    android:background="@color/keyboard_background_color"

    android:layout_width="match_parent"
    android:layout_height="wrap_content">

</android.inputmethodservice.KeyboardView>

Missing few attributes? Don’t worry! in res/drawable folder create key_background.xml. This will be the background of our key.

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

    <item
        android:state_focused="false"
        android:state_selected="false"
        android:state_pressed="false"
        android:drawable="@drawable/normal"
        />

    <item
        android:state_pressed="true"
        android:drawable="@drawable/pressed"
        />

</selector>

In key_background as mentioned, we will need a different background drawable for different state of our key i.e., if its pressed or its in normal or default state.

For this create two more drawable files one normal.xml and another pressed.xml. The code for normal.xml is as follows:

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

    <item android:left="2dp" android:right="2dp">

        <shape android:shape="rectangle">

            <solid android:color="@color/keyboard_divider"/>

        </shape>

    </item>


    <item android:bottom="2dp">

        <shape android:shape="rectangle">

            <solid android:color="@color/keyboard_background_color"/>

        </shape>

    </item>


</layer-list>

And the code for pressed.xml is simple as follows:

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

    <solid android:color="@color/keyboard_pressed"/>

</shape>

Once we are done with background color of keys in different state, now lets set the text attributes of our keyboard keys. In android layout resource directory, create a layout resource file named ‘key_preview.xml’.

We will now using the TextView widget, set the attributes of our key text.

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

Ta Da! Now that we are done with layout, lets move ahead towards coding Android Custom Keyboard Layout.

Coding the android custom keyboard layout

In java folder, under respective directory of your app, create a Service Class that extends InputMethodService and implements KeyboardView.OnKeyboardActionListener.

This class will implements few methods, implement them and write the code as shown below:

package com.androiddvlpr.androiddvlprkeyboard;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.inputmethodservice.InputMethodService;
import android.inputmethodservice.Keyboard;
import android.inputmethodservice.KeyboardView;
import android.media.AudioManager;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.InputConnection;

@TargetApi(Build.VERSION_CODES.CUPCAKE)
@RequiresApi(api = Build.VERSION_CODES.CUPCAKE)
public class AndroidDvlprKeyboard extends InputMethodService implements KeyboardView.OnKeyboardActionListener {

    private KeyboardView keyboardView;
    private Keyboard keyboard;
    Boolean isCaps = false;


    @Override
    public void onPress(int primaryCode) {

    }

    @Override
    public void onRelease(int primaryCode) {

    }

    @SuppressLint("InflateParams")
    @Override
    public View onCreateInputView() {
        keyboardView = (KeyboardView) getLayoutInflater().inflate(R.layout.keyboard,null);
        keyboard = new Keyboard(this, R.xml.qwerty);
        keyboardView.setKeyboard(keyboard);
        keyboardView.setOnKeyboardActionListener(this);
        return keyboardView;
    }

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

        InputConnection inputConnection = getCurrentInputConnection();
        playClick(primaryCode);
        switch (primaryCode){

            case Keyboard.KEYCODE_DELETE:
                inputConnection.deleteSurroundingText(1,0);
                break;

            case Keyboard.KEYCODE_SHIFT:
                isCaps = !isCaps;
                keyboard.setShifted(isCaps);
                keyboardView.invalidateAllKeys();
                break;

            case Keyboard.KEYCODE_DONE:
                inputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_ENTER));
                break;

            default:
                char code = (char) primaryCode;
                if(Character.isLetter(code) && isCaps){
                    code = Character.toUpperCase(code);
                }
                inputConnection.commitText(String.valueOf(code),1);
        }

    }

    private void playClick(int i){

        AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
        switch(i){
            case 32:
                audioManager.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR);
                break;

            case Keyboard.KEYCODE_DONE:
            case 10:
                audioManager.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN);
                break;

            case Keyboard.KEYCODE_DELETE:
                audioManager.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE);
                break;

            default:
                audioManager.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
        }

    }


    @Override
    public void onText(CharSequence text) {

    }

    @Override
    public void swipeLeft() {

    }

    @Override
    public void swipeRight() {

    }

    @Override
    public void swipeDown() {

    }

    @Override
    public void swipeUp() {

    }
}

Manifesting

Before you build the app, go to AndroidManifest.xml file in the manifest folder and don’t forget to declare your service as mentioned below:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androiddvlpr.androiddvlprkeyboard">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <service
            android:name=".AndroidDvlprKeyboard"
            android:label="AndroidDvlpr Keyboard"
            android:permission="android.permission.BIND_INPUT_METHOD">

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

            <intent-filter>

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

            </intent-filter>

        </service>
    </application>

</manifest>

You can download this app source code from direct link here.

Are you interested in customizing the keyboard buttons further? See here our tutorial on customizing android buttons.

Like to create an app from scratch? See here Create Reddit Android App from scratch.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.