Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • How to create custom keyboard in android

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 2.82k
    Comment on it

    In this tutorial we will learn how to create custom keyboard in android. We can customise keyboard by adding extra buttons, change keyboard theme, set image as keyboard background etc.

    Here in this example we are going to add two extra buttons, one for camera and other for gallery, along with qwerty keyboard.

     

    1. First we will create a layout(keyboard.xml) for custom keyboard inside res/layout folder. This layout contains KeyboardView and two buttons.

    <?xml version="1.0" encoding="utf-8"?>
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:id="@+id/mainview"
        >
    
        <android.inputmethodservice.KeyboardView
    
            android:id="@+id/keyboard1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:keyTextColor="#FFFFFF"
            android:padding="4px"
            android:keyTextSize="18sp"
            android:keyPreviewLayout ="@layout/preview"
            />
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_alignParentBottom="true"
            android:background="@color/colorDarkGray">
    
            <Button android:id="@+id/camera"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toLeftOf="@+id/gallery"
                android:text="Camera"
                android:textSize="14sp"
                android:textColor="@android:color/white"
                android:background="@color/colorLightGray"
                android:padding="4px"
                android:layout_marginRight="5dp"
                android:layout_marginBottom="5dp"/>
    
            <Button android:id="@+id/gallery"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:text="Gallery"
                android:textSize="14sp"
                android:textColor="@android:color/white"
                android:background="@color/colorLightGray"
                android:padding="4px"
                android:layout_marginBottom="5dp" />
        </RelativeLayout>
    </LinearLayout>

    2.  Create another layout file preview.xml inside res/layout folder. This layout shows up as a short-lived pop-up whenever a key on the keyboard is pressed. It has a single TextView.

    <?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="#ffff00"
        android:textStyle="bold"
        android:textSize="30sp"
        >
    </TextView>

    3. A soft keyboard is considered as an Input Method Editor (IME) by Android. Modify manifest file by declaring IME as a service. Provide necessary permission

    android.permission.BIND_INPUT_METHOD and set intent filter which matches

    android.view.InputMethod.

    Modify AndroidManifest.xml file by following lines:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.customkeyboarddemo">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <service
                android:name="com.customkeyboarddemo.CustomKeyboardService"
                android:label="@string/simple_ime"
                android:permission="android.permission.BIND_INPUT_METHOD"
                android:enabled="true"
                android:exported="true">
                <meta-data
                    android:name="android.view.im"
                    android:resource="@xml/method" />
    
                <intent-filter>
                    <action android:name="android.view.InputMethod" />
                </intent-filter>
            </service>
        </application>
    
    </manifest>

    4. The service tag in the AndroidManifest file contains a meta-data tag that references an XML file named method.xml. This file contains details about the input method and its subtypes. Create method.xml file inside res/xml file

    <?xml version="1.0" encoding="utf-8"?>
    <input-method xmlns:android="http://schemas.android.com/apk/res/android">
        <subtype
            android:label="subtype_en_US"
            android:imeSubtypeLocale="en_US"
            android:imeSubtypeMode="keyboard" />
    </input-method>

    5. Edit string.xml file

    <resources>
        <string name="app_name">Custom Keyboard Demo</string>
        <string name="simple_ime">CustomKeyboardDemo</string>
        <string name="subtype_en_US">English (US)</string>
    </resources>

    6. Edit colors.xml file

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="colorDarkGray">#2E2E2E</color>
        <color name="colorLightGray">#585858</color>
    </resources>

    7. The details of the keyboard keys and it's position are defined in an xml file. Every key has the following attributes:

    • keyLable: The actual text display on a key.
    • codes: This attribute contains the Unicode value of a character, the key represents.

    Create qwerty.xml file inside res/xml folder.

    <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
        android:keyWidth="10%p"
        android:horizontalGap="0px"
        android:verticalGap="0px"
        android:keyHeight="40dp"
        >
        <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"/>
            <Key android:codes="54" android:keyLabel="6"/>
            <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="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
            <Key android:codes="119" android:keyLabel="w"/>
            <Key android:codes="101" android:keyLabel="e"/>
            <Key android:codes="114" android:keyLabel="r"/>
            <Key android:codes="116" android:keyLabel="t"/>
            <Key android:codes="121" android:keyLabel="y"/>
            <Key android:codes="117" android:keyLabel="u"/>
            <Key android:codes="105" android:keyLabel="i"/>
            <Key android:codes="111" android:keyLabel="o"/>
            <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
        </Row>
        <Row>
            <Key android:codes="97" android:keyLabel="a" android:keyEdgeFlags="left"/>
            <Key android:codes="115" android:keyLabel="s"/>
            <Key android:codes="100" android:keyLabel="d"/>
            <Key android:codes="102" android:keyLabel="f"/>
            <Key android:codes="103" android:keyLabel="g"/>
            <Key android:codes="104" android:keyLabel="h"/>
            <Key android:codes="106" android:keyLabel="j"/>
            <Key android:codes="107" android:keyLabel="k"/>
            <Key android:codes="108" android:keyLabel="l"/>
            <Key android:codes="35,64" android:keyLabel="\# \@" android:keyWidth="20%p" android:keyEdgeFlags="right"/>
        </Row>
        <Row>
            <Key android:codes="-1" android:keyLabel="CAPS" android:keyWidth="20%p" android:keyEdgeFlags="left"/>
            <Key android:codes="122" android:keyLabel="z"/>
            <Key android:codes="120" android:keyLabel="x"/>
            <Key android:codes="99" android:keyLabel="c"/>
            <Key android:codes="118" android:keyLabel="v"/>
            <Key android:codes="98" android:keyLabel="b"/>
            <Key android:codes="110" android:keyLabel="n"/>
            <Key android:codes="109" android:keyLabel="m"/>
            <Key android:codes="46" android:keyLabel="."/>
            <Key android:codes="63,33,58" android:keyLabel="\? ! :" android:keyEdgeFlags="right"/>
        </Row>
        <Row android:rowEdgeFlags="bottom">
            <Key android:codes="44" android:keyLabel="," android:keyWidth="10%p"  android:keyEdgeFlags="left"/>
            <Key android:codes="47" android:keyLabel="/" android:keyWidth="10%p" />
            <Key android:codes="32" android:keyLabel="SPACE" android:keyWidth="40%p" android:isRepeatable="true"/>
            <Key android:codes="-5" android:keyLabel="DEL" android:keyWidth="20%p" android:isRepeatable="true"/>
            <Key android:codes="-4" android:keyLabel="DONE" android:keyWidth="20%p" android:keyEdgeFlags="right"/>
        </Row>
      </Keyboard>

    8. Now create a service class CustomKeyboardService.java which will extend InputMethodService class and implements KeyboardView.OnKeyboardActionListener interface. The OnKeyboardActionListener always called whenever a key is pressed on a keyboard.

    When a keyboard is created, the onCreateInputView() is called. Initialize all the member variables of the Service class in this method. We also have set click listener for that two extra buttons (camera and gallery).

    Next, we create a method playClick(int keyCode), that plays a sound when a key is pressed.

    Finally, update onKey() method, so that our app's keyboard can communicate with input fields.

    Below is the service class:

    package com.customkeyboarddemo;
    
    import android.content.Context;
    import android.content.Intent;
    import android.inputmethodservice.InputMethodService;
    import android.inputmethodservice.Keyboard;
    import android.inputmethodservice.KeyboardView;
    import android.media.AudioManager;
    import android.view.KeyEvent;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.inputmethod.InputConnection;
    import android.widget.Button;
    
    /**
     * Created by anita on 21/3/17.
     */
    
    public class CustomKeyboardService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
    
        private static  KeyboardView keyboardView;
        private Keyboard keyboard;
        private boolean caps = false;
        private Button btGallery,btCamera;
    
        @Override
        public View onCreateInputView() {
            System.out.println("onCreateInputView.........");
            View view = null;
            LayoutInflater inflater1 = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater1.inflate(R.layout.keyboard, null);
            view.invalidate();
    
            keyboardView = (KeyboardView) view.findViewById(R.id.keyboard1);
            keyboard = new Keyboard(this, R.xml.qwerty);
    
            keyboardView.setKeyboard(keyboard);
            keyboardView.setOnKeyboardActionListener(this);
            btGallery = (Button)view.findViewById(R.id.gallery);
            btGallery.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    openCameraOrGallery("gallery");
                }
            });
            btCamera = (Button)view.findViewById(R.id.camera);
            btCamera.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    openCameraOrGallery("camera");
                }
            });
            return view;
    
    
        }
        private void playClick(int keyCode){
            AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
            switch(keyCode){
                case 32:
                    am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR);
                    break;
                case Keyboard.KEYCODE_DONE:
                case 10:
                    am.playSoundEffect(AudioManager.FX_KEYPRESS_RETURN);
                    break;
                case Keyboard.KEYCODE_DELETE:
                    am.playSoundEffect(AudioManager.FX_KEYPRESS_DELETE);
                    break;
                default: am.playSoundEffect(AudioManager.FX_KEYPRESS_STANDARD);
            }
        }
        @Override
        public void onKey(int primaryCode, int[] keyCodes) {
            InputConnection ic = getCurrentInputConnection();
            playClick(primaryCode);
    
            switch(primaryCode){
                case Keyboard.KEYCODE_DELETE :
                    ic.deleteSurroundingText(1, 0);
                    break;
                case Keyboard.KEYCODE_SHIFT:
                    caps = !caps;
                    keyboard.setShifted(caps);
                    keyboardView.invalidateAllKeys();
                    break;
                case Keyboard.KEYCODE_DONE:
                    ic.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER));
                    break;
                default:
                    char code = (char)primaryCode;
                    if(Character.isLetter(code) && caps){
                        code = Character.toUpperCase(code);
                    }
                    ic.commitText(String.valueOf(code),1);
            }
        }
    
        private void openCameraOrGallery(String str){
            Intent intent = new Intent(getBaseContext(), MainActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
            if(str.equals("camera"))
                intent.putExtra("request", "camera");
            else
                intent.putExtra("request", "gallery");
            getApplicationContext().startActivity(intent);
        }
        @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() {
    
        }
        @Override public void onCreate() {
            super.onCreate();
        }
    
    }
    

    9. Image selected from gallery or captured by camera will show in this application's activity_main.xml file.

    <?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:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="com.customkeyboarddemo.MainActivity">
    
        <EditText android:id="@+id/edittext"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/imageView"
            android:layout_below="@id/edittext"/>
    
    </RelativeLayout>
    

    10. Finally we have a MainActivity.java class where we will implement functionality to open camera and to select image from gallery

    package com.customkeyboarddemo;
    
    import android.content.Intent;
    import android.graphics.Bitmap;
    import android.net.Uri;
    import android.os.Environment;
    import android.provider.MediaStore;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.ImageView;
    import java.io.File;
    
    public class MainActivity extends AppCompatActivity {
    
        private static int RESULT_LOAD_IMAGE = 1;
        private static int RESULT_CAPTURE_IMAGE = 2;
        static MainActivity mainActivity;
        ImageView ivSelectedImage;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mainActivity = this;
            ivSelectedImage = (ImageView) findViewById(R.id.imageView);
            if(getIntent().getExtras() != null){
                if(getIntent().getStringExtra("request")!= null && getIntent().getStringExtra("request").equals("camera"))
                    openCamera();
                else
                    openGallery();
            }
    
        }
        @Override
        protected void onResume(){
            super.onResume();
        }
        private void openCamera(){
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            File f = new File(Environment.getExternalStorageDirectory(),"image.jpg");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
            startActivityForResult(intent, RESULT_CAPTURE_IMAGE);
    }
        public void openGallery(){
    
            Intent intent;
            if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
                intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            } else {
                intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI);
            }
            intent.putExtra("return-data", true);
            intent.setType("image/*");
            startActivityForResult(intent, RESULT_LOAD_IMAGE);
        }
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            Uri selectedImageUri = null;
            if (resultCode == RESULT_OK) {
    
    
                if (requestCode == RESULT_CAPTURE_IMAGE ) {
                    File f = new File(Environment.getExternalStorageDirectory().toString()+File.separator+"image.jpg");
                    Uri imgUri = Uri.fromFile(f);
                    selectedImageUri = imgUri;
                }else if (requestCode == RESULT_LOAD_IMAGE) {
                    // Get the url from data
                    selectedImageUri = data.getData();
                }
                if(null != selectedImageUri) {
                   ivSelectedImage.setImageURI(selectedImageUri);
                }
            }
    
        }
    
    }

    11. The custom keyboard is ready to use. Compile your code and run it on an Android device. To use this, it should first be activated on device and you can do it from settings:

    Settings --> Language & input --> Current Keyboard --> select your keyboard

    Now, you are ready to use your custom keyboard from any app in your device.

    Thanks.

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: