Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • How to create Custm Keyboard in Android?

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 3
    • 0
    • 1.7k
    Comment on it

    Hello Guys,

    This is very important tutorial through which, we will learn how to create a custom keyboard without using third party library in the android application. This tutorial fully customizes device keyboard. We will go step by step to learn this process.

    Step1- Introduction

    Custom keyboard process provides full customization of your device keyboard. Through this tutorial, you can set device keyboard wallpaper, change keyboard themes, change keyboard key background color etc.

    Step2- Create two directory colors.xml and strings.xml inside 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>
        <color name="colorTransparent">#20FFFFFF</color>
        <color name="colorBack">#80AFC2</color>
        <color name="themes1_keystroke">#6EE0D8</color>
        <color name="themes1_color1">#5048B6AA</color>
        <color name="themes1_color2">#501E9799</color>
        <color name="colorWhite">#FFFFFF</color>
        <color name="themes2_keystroke">#B8B0A6</color>
        <color name="themes2_color1">#2D4A73</color>
        <color name="themes2_color2">#2963B9</color>
    </resources>
    

    strings.xml

     

    <resources>
        <string name="app_name">MyKeyboard</string>
        <string name="action_settings">Settings</string>
    
        <string name="simple_ime">MyCustomKeyboard</string>
        <string name="subtype_en_US">English (US)</string>
    
        <string name="keyboad_background">Keyboard Background Image</string>
        <string name="themedefault">Theme Default</string>
        <string name="themeone">Theme one</string>
        <string name="themetwo">Theme two</string>
    </resources>
    

     

    Step3- Create a parent directory resource xml under res/xml and put following two more child directory resource method.xml and qwerty.xml.

    res/xml/method.xml:

    In this resource file, we define keyboard input method such as keyboard default language, keyboard locale language, keyboard mode etc.
     

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

    res/xml/qwerty.xml

    This is the important file for a custom keyboard. In this file, we define all keyboard keys row with all numeric and alphabetic. We also define keys height, width and gaps between keys.
     

    <?xml version="1.0" encoding="utf-8"?>
    <Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
        android:keyWidth="10%p"
        android:horizontalGap="8px"
        android:verticalGap="8px"
        android:keyHeight="35dp">
    
    
        <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:keyEdgeFlags="right"/>-->
        </Row>
    
    
        <Row>
            <Key android:codes="-1" android:keyLabel="CAPS" android:keyWidth="18%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="-5" android:keyIcon="@drawable/ic_clear_white_24dp"  android:isRepeatable="true"/>
    
        </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="46" android:keyLabel="."/>
           <Key android:codes="63,33,58" android:keyLabel="\? ! :" android:keyEdgeFlags="right"/>
            <Key android:codes="32" android:keyLabel="SPACE" android:keyWidth="35%p" android:isRepeatable="true"/>
            <Key android:codes="-4" android:keyLabel="DONE" android:keyWidth="20%p" android:keyEdgeFlags="right"/>
        </Row>
    
    </Keyboard>

     

    Step4- Create a menu resource file to show options for themes and keyboard wallpaper .

    res/menu/main_menu.xml
     

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android" >
        <item
            android:id="@+id/action1"
            android:title="@string/keyboad_background"
            />
    
        <item
            android:id="@+id/defaultAction"
            android:title="@string/themedefault"
            />
    
        <item
            android:id="@+id/action2"
            android:title="@string/themeone"
            />
    
        <item
            android:id="@+id/action3"
            android:title="@string/themetwo"
            />
    
    </menu>

     

    Step5- Now, we will create custom themes layout file under main layout resource folder

    •   Default Theme

    res/layout/default_theme.xml

    <?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="250dp"
        android:orientation="vertical"
    
        android:id="@+id/mainview">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@color/colorBack">
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:padding="10dp"
                android:id="@+id/menu_item"
                android:layout_alignParentRight="true"
                android:src="@drawable/ic_more_vert_white_24dp"/>
    
        </RelativeLayout>
    
    <android.inputmethodservice.KeyboardView
    
        android:id="@+id/keyboard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:keyTextColor="@color/colorAccent"
        android:padding="4px"
        android:background="@drawable/images"
        android:keyTextSize="18sp"
        android:keyBackground="@color/colorTransparent"
        android:keyPreviewLayout ="@layout/preview"
        />
    </LinearLayout>

     

    • Theme One

    res/layout/themes1.xml
     

    <?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="250dp"
        android:orientation="vertical"
        android:id="@+id/mainview">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@color/themes1_keystroke">
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:padding="10dp"
                android:id="@+id/menu_item"
                android:layout_alignParentRight="true"
                android:src="@drawable/ic_more_vert_white_24dp"/>
    
        </RelativeLayout>
    
        <android.inputmethodservice.KeyboardView
    
            android:id="@+id/keyboard1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:keyTextColor="@color/colorWhite"
            android:padding="4px"
            android:keyTextSize="18sp"
    
            android:background="@drawable/images"
            android:keyBackground="@drawable/themes1_bg"
            android:keyPreviewLayout ="@layout/preview"
            />
    </LinearLayout>

     

    • Theme two

    res/layout/themes2.xml
     

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:orientation="vertical"
    
        android:id="@+id/mainview">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@color/themes2_keystroke">
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:padding="10dp"
                android:id="@+id/menu_item"
                android:layout_alignParentRight="true"
                android:src="@drawable/ic_more_vert_white_24dp"/>
    
        </RelativeLayout>
    
        <android.inputmethodservice.KeyboardView
            android:id="@+id/keyboard2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:keyTextColor="@color/colorWhite"
            android:padding="4px"
            android:keyTextSize="18sp"
            android:background="@drawable/images"
            android:keyBackground="@drawable/themes2_bg"
            android:keyPreviewLayout ="@layout/preview"
            />
    
    
    </LinearLayout>

     

    4- Create  parent layout

    res/layout/parentlayout.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:id="@+id/parentlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
    </LinearLayout>
    
    

     

    5- Create preview layout

    res/layout/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="30dp"
        android:gravity="center"
        android:background="#FFFFFF"
        android:textStyle="bold"
        android:textSize="25sp"
        >
    </TextView>
    

     

    Step6- Now we will create main keyboard service MyKeyboardService

    MyKeyboardService extends InputMethodService, InputMethodService provides a standard implementation of an InputMethod, which final implementations can derive from and customize. The InputMethodService provides a basic framework for standard UI elements (input view, candidates view, and running in fullscreen mode), but it is up to a particular implementor to decide how to use them. For example, one input method could implement an input area with a keyboard, another could allow the user to draw text, while a third could have no input area (and thus not be visible to the user) but instead listen to audio and perform text to speech conversion.

    Refrence Url:- https://developer.android.com/reference/android/inputmethodservice/InputMethodService.html

     

    MykeyboardService.java

    /**
     * Created by arvind on 8/7/16.
     */
    public class MyKeyboardService extends InputMethodService implements KeyboardView.OnKeyboardActionListener {
    
        private static  KeyboardView kv;
        private Keyboard keyboard;
        private ImageView imageView;
        private static int RESULT_LOAD_IMAGE = 1;
        Drawable d;
        public static  LinearLayout linearLayout;
        private boolean caps = false;
        private String themes="default";
        private static Drawable drawable;
    
    
    
        @Override
        public void onKey(int primaryCode, int[] keyCodes) {
            System.out.println("onKeyPressed.");
    
            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);
                    kv.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);
            }
        }
    
        @Override
        public void onPress(int primaryCode) {
            System.out.println("onPress");
        }
    
        @Override
        public void onRelease(int primaryCode) {
            System.out.println("onRelease");
        }
    
        @Override
        public void onText(CharSequence text) {
            System.out.println("onText");
        }
    
        @Override
        public void swipeDown() {
            System.out.println("onSwipeDown");
        }
    
        @Override
        public void swipeLeft() {
            System.out.println("onSwipeLeft");
        }
    
        @Override
        public void swipeRight() {
        }
    
        @Override
        public void swipeUp() {
        }
    
        @Override public void onCreate() {
            super.onCreate();
        }
    
    
        @Override
        public View onCreateInputView() {
            System.out.println("onCreateInputView.........");
            View view = null;
    
    
            if (themes != null && themes.equals("one")) {
    
    
                System.out.println("theme one....");
    
                LayoutInflater inflater1 = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater1.inflate(R.layout.themes1, null);
                view.invalidate();
    
                imageView = (ImageView) view.findViewById(R.id.menu_item);
                imageView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        openOptionsMenu(v);
                    }
                });
                kv = (KeyboardView) view.findViewById(R.id.keyboard1);
                //kv.setBackgroundResource(R.drawable.images);
                keyboard = new Keyboard(this, R.xml.qwerty);
    
                kv.setKeyboard(keyboard);
                kv.setOnKeyboardActionListener(this);
    
               kv.setBackground(drawable);
    
    
                return view;
    
            }else if (themes != null && themes.equals("two")) {
    
    
                System.out.println("theme two....");
    
                LayoutInflater inflater1 = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater1.inflate(R.layout.themes2, null);
                view.invalidate();
    
                imageView = (ImageView) view.findViewById(R.id.menu_item);
                imageView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        openOptionsMenu(v);
                    }
                });
                kv = (KeyboardView) view.findViewById(R.id.keyboard2);
                //kv.setBackgroundResource(R.drawable.images);
                keyboard = new Keyboard(this, R.xml.qwerty);
    
                kv.setKeyboard(keyboard);
                kv.setOnKeyboardActionListener(this);
    
                kv.setBackground(drawable);
    
    
                return view;
    
            } else if (themes != null && themes.equals("default")) {
                System.out.println("theme default....");
    
                LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                view = inflater.inflate(R.layout.default_theme, null);
    
    
                imageView = (ImageView) view.findViewById(R.id.menu_item);
                imageView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        openOptionsMenu(v);
                    }
                });
                kv = (KeyboardView) view.findViewById(R.id.keyboard);
                //kv.setBackgroundResource(R.drawable.images);
                keyboard = new Keyboard(this, R.xml.qwerty);
    
                kv.setKeyboard(keyboard);
                kv.setOnKeyboardActionListener(this);
    
                kv.setBackground(drawable);
                return view;
    
            }else {
                return  null;
            }
    
    
    }
    
        // This function open options menu
        private void openOptionsMenu(View view){
            /** Instantiating PopupMenu class */
            PopupMenu popup = new PopupMenu(getBaseContext(), view);
    
            /** Adding menu items to the popumenu */
            popup.getMenuInflater().inflate(R.menu.menu_main, popup.getMenu());
    
            /** Defining menu item click listener for the popup menu */
            popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    Toast.makeText(getBaseContext(), "Click Item  " + item.getTitle(), Toast.LENGTH_SHORT).show();
    
                    if (item.getTitle().equals("Keyboard Background Image")) {
    
    
                        Intent intent = new Intent(getBaseContext(), MainActivity.class);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        intent.putExtra("from", "service");
                        getApplicationContext().startActivity(intent);
    
                    }else if(item.getTitle().equals("Theme one")){
                        themes="one";
                        setInputView(onCreateInputView());
                        
                    }else if(item.getTitle().equals("Theme two")){
                        themes="two";
                        setInputView(onCreateInputView());
                        
                    } else if(item.getTitle().equals("Theme Default")){
    
                        themes="default";
                        setInputView(onCreateInputView());
                    }
                    return true;
                }
            });
    
            /** Showing the popup menu */
            popup.show();
        }
    
        private void playClick(int keyCode){
            AudioManager am = (AudioManager)getSystemService(AUDIO_SERVICE);
            switch(keyCode){
                case 32:
                    am.playSoundEffect(AudioManager.FX_KEYPRESS_SPACEBAR);
                    break;
                case -1:
                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);
            }
        }
    
    
    public static  void setBackGroundImage(Bitmap bitmap){
     
        try {
    
            drawable=new BitmapDrawable(Resources.getSystem(),bitmap);
            kv.setBackground(drawable);
        }catch (Exception e){
    
        }
    
    }
    
       
    
    }

     

    Step7- Create a MainActivity class

    This main class nothing do but use to open gallery when user tries to select images for keyboard wallpaper. In this activity, we need to define two methods which call from InputMethodService. First method is doChangeBackground(), this method call when user will try to change keyboard wallpaper.

    MainActivity.java

    // Defined class variable

    private static int RESULT_LOAD_IMAGE = 1;
    static MainActivity mainActivity;
    private Bitmap yourSelectedImage;

     

    // onCreate() method

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        mainActivity=this;
    
        //String str=getIntent().getStringExtra("from");
        if(getIntent().getExtras()!=null){
            System.out.println("not null");
            doChangeKeyBoardBackground();
        }else{
            System.out.println("null");
        }
    }
    
    

    // method call from InputMethodService

     
    // change default_theme background images
    public void doChangeKeyBoardBackground(){
    
        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 onActivityResult method

     @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            if (resultCode == RESULT_OK) {
    
    
                if (requestCode == RESULT_LOAD_IMAGE) {
                    // Get the url from data
                    Uri selectedImageUri = data.getData();
    
                    if (null != selectedImageUri) {
                        // Get the path from the Uri
                        getPathFromURI(selectedImageUri);
                        // finish();
                         MyKeyboardService.setBackGroundImage(yourSelectedImage);
                         finish();
    
                    }
                }
            }
        }
    
        /* Get the real path from the URI */
        public String getPathFromURI(Uri contentUri) {
            String res = null;
            String[] proj = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);
            if (cursor.moveToFirst()) {
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                res = cursor.getString(column_index);
                yourSelectedImage = BitmapFactory.decodeFile(res);
            }
            cursor.close();
            return res;
        }
    

     

    Step 7- Defined here application manifest.xml file

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.customkeyboard">
    
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
    
        <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"
                android:label="@string/app_name"
                android:theme="@style/AppTheme.NoActionBar"
                >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
            <service android:name=".MyKeyboardService"
                android:label="@string/simple_ime"
                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>
    

     

    Step 8- Set your custom keyboard as default keyboard

    First, open device settings files then select Language & Input option, select Current Keyboard option and finally choose MyCustomKeyboard options.

    settings -> Language & Input -> Current Keyboard -> MyCustomKeyboard

    Now your custom keyboard will work as default keyboard.

     

    Note:- We have attached application screen shot. You can also get complete source code from attachment.

     

    How to create Custm Keyboard in Android?

 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: