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:
Need some career advice or prepping for an Android developer interview? Hit me up on Topmate.io, and let's chat!
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.