[GUIDE] The right Soft Keyboard (+adding a CustomKeyboard)

SimplicityApks

Senior Member
May 26, 2013
354
344
0
Aachen
Hi devs,

During development of my app (see my signature), I researched a bit and finally found a quite nice way to implement a custom keyboard which is only shown in your app easily.
Much of this is taken from Maarten Pennings' awesome guide here, thanks to him and feel free to read it as well.
So I thought I'd extend his work with this guide which also takes a look at why you'd want to use one or the other keyboard. Enjoy! :victory:


Main-error.jpg
Limits of the Android IME
Any kind of text input (password, number, address, etc.) is usually handled very nicely using the android:inputType attribute (or the corresponding setter in java) on the EditText field.
But as soon as you have to deny some characters, for instance you want the user to insert a file name, it gets more complicated since there is no inputType for that.

The way to achieve that would be to implement your own KeyListener like this:
Java:
import android.text.method.NumberKeyListener;
//...

	// set a new KeyListener onto your desired EditText, overriding the default one:
	EditText edit = findViewById(R.id.edittext);
	edit.setKeyListener(new NumberKeyListener(){

		@Override
		public int getInputType() {
			// should be the same as android:inputType, for all numbers including decimal and negative:
			return (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_NUMBER_FLAG_SIGNED);
		}

		@Override
		protected char[] getAcceptedChars() {
			// declare your desired chars here, ONLY those will be accepted!
			// for instance numbers:
			char [] res = {'1', '2', '3',
				'4', '5', '6', 
				'7', '8', '9', 
				'0', '+', '-', '*', '/',
				'(', ')', '.', ',', ' ', '^', '!',
				// alphabet:
				'a', 'b', 'c', 'd', 'e', 
				'f', 'g', 'h', 'i', 'j', 
				'k', 'l', 'm', 'n', 'o',
				'p', 'q', 'r', 's', 't', 
				'u', 'v', 'w', 'x', 'y',
				'z'
			};
			return res;
		}	
	});
The problem is that the keys are still present and therefore distracting and irritating to the user, because nothing happens on click.
And also, there might be a much easier and better accessible layout for your set of keys. In the following I will tell you how to integrate such a custom layout using the KeyboardView class, but first let's take a look at the advantages of both keyboards:


Android IME or KeyboardView???
The answer to this question is tightly depending on the task you want the user to fulfil, and also on how much freedom you want to give him. The high customizablility and its theming options are a strong point for the KeyboardView, but be warned that since this View was added in API level 3 (and never updated I think) there are a couple of bugs which you have to workaround.
A standard keyboard is more familiar to the user and is often also a third-party keyboard and therefore more customizable. But this also has its downsides since there is no guarantee that the IME will display the characters you need.
Note that you will not be able to get a working cursor image easily with the KeyboardView (though the cursor works as it should, just the blue arrow below it won't be displayed).

Main-log2.jpg

For simple tasks where just a few buttons will be useless, such as when asking for a filename the normal IME is recommended. But for various operations you'll find the KeyboardView to be much cleaner.
If you decided to try the KeyboardView, here's how it works:


Adding a CustomKeyboard
NOTE: I will only cover how to implement such a Keyboard, if you want to know how it works in detail check out the third chapter in Maarten Pennings' guide.

First, since it is a view, you will need to manually insert the following to the xml layout file of all activities where you want to use it:
Code:
<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" />
Put it in a relative layout container, though it should also work in other ones. Most important is that it is the topmost container in the view hierarchy.

Second, you need an xml file where all the keys and their layout are stored for the KeyboardView to inflate. For a start, you can take the one Maarten Pennings has posted or download mine here: View attachment keyboard_layout.txt (xda doesn't support .xml files, so just rename it to keyboard_layout.xml!)
Move that file to your res/xml/ folder, you can create other layouts for landscape using res/xml-land/

You have to play around with that file a bit to get your desired layout, here are some tips:
  • Start by designing it on paper, then write it as a comment (ASCII-Art‎?) so you have it properly lined up and always at your hand while coding
  • Including gaps of half a key or so to separate different areas works nicely
  • Highlight important keys either with a different android:keyBackground or by making them larger than the others.
  • Leave the android:horizontalGap attribute untouched on Keyboard level, this will probably break the key lineup
  • Calculate the key width like so: width = 100/(keysPerRow + numberOfGaps)
  • Set the android:keyHeight on Keyboard level to something that rows*keyHeight is about 40%-50%.
  • For every key label which is longer a single character, use the corresponding ASCII-integer as key code (android:codes), otherwise pick a negative number or one that's higher than 256
  • Use android:isRepeatable="true" for keys to press and hold for multiple clicks like the delete key
  • If you want to display a popup keyboard on hold, you should rather make a popup window yourself or use a dialog rather than using the android:popupKeyboard attribute.
  • For inserting more than one char on click, use the android:keyOutputText on key level or override the specific keycode in the onKey() method in CustomKeyboard.java
As I said, you will need some patience doing this since there is neither help nor documentation on the xml namespaces.

Third, there are a couple of icons required for some keys like the delete key. You can either use the ones provided in the guide, but I suggest downloading the original holo android icons from the different drawable folders here.
Take the sym_keyboard_... files that you think you'll need and place them in the respective res/drawable-ydpi folder. Set the android:keyIcon attribute to @drawable/sym_keyboard_... for those special keys.

Fourth, we need a java class to process the clicks and provide the methods for showing and hiding the keyboard. Luckily, you take mine here: View attachment CustomKeyboard.txt (again, rename it to CustomKeyboard.java)
Copy that file into your src/com/package/name and change the package to your app.
This class is heavily based of the one Maarten Pennings has come up with, but with an actually working cursor, so that you can tap or drag to move the cursor. I included haptic feedback (set it using enableHapticFeedback(true)) and an easy way to add chooser dialogs if you want to have multiple insertions in one key (see the onClick(...) method); This looks like this:
Main-math-additional.jpg
If you are using any special keys or dialogs as popups, you will need to edit the onKey() or the onClick() method like I did.

Fifth, in your onCreate() method after setContentView(...) you just need to register every EditText that you want to use the keyboard on like so:
Java:
// initialize the instance variable customKeyboard
	customKeyboard = new CustomKeyboard(this, R.id.keyboardview, R.xml.keyboard_layout);
	// register the edittext
	customKeyboard.registerEditText(R.id.edittext);
For a hiding keyboard if you press the Back key, add the following to your activity:
Java:
@Override 
	public void onBackPressed() {
        if(customKeyboard!=null && customKeyboard.isCustomKeyboardVisible() ) customKeyboard.hideCustomKeyboard(); else super.onBackPressed();
    }
Congrats, you have finished adding a CustomKeyboard and can now test and further improve it :good:
Read on if you want to theme it further (let's face it, the default theme is still from the first versions of android).
 
Last edited:

SimplicityApks

Senior Member
May 26, 2013
354
344
0
Aachen
Theming your Keyboard

Theming the KeyboardView

To make your newly created keyboard fit more to the overall style of your app, it is crucial to theme it.

Here are some attributes which you'll want to customize:
Code:
<!-- on KeyboardView level: (in android.inputmethodservice.KeyboardView in your activity) -->
	android:keyBackground
	android:keyTextColor
	android:keyTextSize
	android:background
	<!-- on Key level: -->
	android:isSticky 
	<!-- for toggle keys like shift or ALT only -->
	android:isModifier
These are all pretty self-explanatory, the most important one being the keyBackground.
You will need different drawables for each of the keys states including normal, pressed, active, popup and either light or dark theme.

As an example, here's how I made the holo style: Basically I took the holo drawables from source and added android:keyBackground="@drawable/btn_keyboard_key_ics" in our KeyboardView (not Keyboard!).

  1. Download those icons from here.
  2. Specifically, you need the btn_keyboard_key_ics.xml file in the drawable folder and all the btn_keyboard_key_... from the xhdpi, hdpi and mdpi folder that you need, at least btn_keyboard_key_dark_normal_holo and btn_keyboard_key_dark_pressed_holo.
  3. The btn_keyboard_key_ics.xml goes into your res/drawable folder and all the others should be dumped into their respective res/drawable-ydpi folder.
  4. From the key_ics file delete all items where you didn't download the .9.pngs so they don't give compilation errors.
I hope you found this helpful and I could save you a bit of work. If you have any questions or suggestions, feel free to post them here!

This guide was featured on the portal on 26th October (thanks Will Verduzco!)
 
Last edited:

anurag.dev1512

Senior Member
Aug 8, 2013
126
210
0
Can we edit the third party stock keyboards....

Theming the KeyboardView

To make your newly created keyboard fit more to the overall style of your app, it is crucial to theme it.


I hope you found this helpful and I could save you a bit of work. If you have any questions or suggestions, feel free to post them here!

This guide was featured on the portal on 26th October (thanks Will Verduzco!)
Since i like the stock keyboard of htc one ... just wanted to know if i replace the resources of stock keyboard of AOSP with that of keyboard from
htc one will it work or do i nedd to do some modding....
 
  • Like
Reactions: adarsh.cop

SimplicityApks

Senior Member
May 26, 2013
354
344
0
Aachen
Since i like the stock keyboard of htc one ... just wanted to know if i replace the resources of stock keyboard of AOSP with that of keyboard from
htc one will it work or do i nedd to do some modding....
You mean you want to have a KeyboardView in your app with the layout files from the HTC keyboard? Sure, that'll work, you only need to get the resources (decompile keyboard app?). Some layout adjustments might be needed of course...
 

anurag.dev1512

Senior Member
Aug 8, 2013
126
210
0
reply

You mean you want to have a KeyboardView in your app with the layout files from the HTC keyboard? Sure, that'll work, you only need to get the resources (decompile keyboard app?). Some layout adjustments might be needed of course...
no bro i m saying to mod the stock keyboard of jellybean with that of stock keyboard of htc one...
 
  • Like
Reactions: adarsh.cop

SimplicityApks

Senior Member
May 26, 2013
354
344
0
Aachen
no bro i m saying to mod the stock keyboard of jellybean with that of stock keyboard of htc one...
OK, sorry, I didn't read the title of your post...

That should be possible, although I have no idea about decompiling and modding. From what I understand, you could try making an XPosed module, that should work and is better since it can be applied at runtime.
 

Saurabh Shah

Senior Member
Jun 15, 2013
115
169
0
Bangalore
www.thehackwall.com
Hi devs,

During development of my app (see my signature), I researched a bit and finally found a quite nice way to implement a custom keyboard which is only shown in your app easily.
Much of this is taken from Maarten Pennings' awesome guide here, thanks to him and feel free to read it as well.
So I thought I'd extend his work with this guide which also takes a look at why you'd want to use one or the other keyboard. Enjoy! :victory:


View attachment 2347941


Congrats, you have finished adding a CustomKeyboard and can now test and further improve it :good:
Read on if you want to theme it further (let's face it, the default theme is still from the first versions of android).
Nice :)
 
Last edited:

tejal

New member
Jan 17, 2014
1
0
0
Theming the KeyboardView

To make your newly created keyboard fit more to the overall style of your app, it is crucial to theme it.


I hope you found this helpful and I could save you a bit of work. If you have any questions or suggestions, feel free to post them here!

This guide was featured on the portal on 26th October (thanks Will Verduzco!)
hi... I am not able to download resources for custom keyboard... please help me
 

misleading93

New member
Aug 5, 2014
2
0
0
Thanks for the tutorial, really helped me with my project as I need a custom keyboard. But I would like to ask, how do I add a second page to the keyboard as I need more entries to it. Is there a way to add like a small button in the keyboard 1/2 and when you press it, it'll go to the 2nd page of it.
 

SimplicityApks

Senior Member
May 26, 2013
354
344
0
Aachen
Thanks for the tutorial, really helped me with my project as I need a custom keyboard. But I would like to ask, how do I add a second page to the keyboard as I need more entries to it. Is there a way to add like a small button in the keyboard 1/2 and when you press it, it'll go to the 2nd page of it.
Mmmmh didn't think about that so far... Have you tried wrapping 2 keyboardviews in a viewpager?
 

misleading93

New member
Aug 5, 2014
2
0
0
Mmmmh didn't think about that so far... Have you tried wrapping 2 keyboardviews in a viewpager?
I think I got it somehow.
I made a small key in the current keyboard. An example maybe like SYM which represents Symbol, so if you press it, it'll go to the view on keyboard full of symbols. Just had to repeat actually.

Edit: It seems like I can't post the code or part of it. Says that my post was flagged by the system and was blocked from submitting. I want to show how, but it seems it doesn't allow me haha.
 

SimplicityApks

Senior Member
May 26, 2013
354
344
0
Aachen
I think I got it somehow.
I made a small key in the current keyboard. An example maybe like SYM which represents Symbol, so if you press it, it'll go to the view on keyboard full of symbols. Just had to repeat actually.

Edit: It seems like I can't post the code or part of it. Says that my post was flagged by the system and was blocked from submitting. I want to show how, but it seems it doesn't allow me haha.
Lol sometimes the system is against us..., well nice you figured it out ;)
 

kva123

Member
Dec 18, 2010
28
3
0
I am lost/stuck

First off I would like to thank Simplicity for such a simple guide and tutorial on how to set the custom keyboard up. Secondly even if it was very simple I obviously cannot follow directions and have done something wrong and even though my custom keyboard pops up and I am able to press the button, I am not able to get the edittext field to register the onclicks of the keys thus resulting in the buttons doing nothing. I have pmed Simplicity and was requested by him to post this question in the thread for others in case anyone else runs into this issue.


I have attached both the xml and java file to the post.

Hope someone can help and also hope this problem I ran into will help others if they are stuck at the same place.

Once again a big big big Thanks to SimplicityApks.
 

Attachments

SimplicityApks

Senior Member
May 26, 2013
354
344
0
Aachen
First off I would like to thank Simplicity for such a simple guide and tutorial on how to set the custom keyboard up. Secondly even if it was very simple I obviously cannot follow directions and have done something wrong and even though my custom keyboard pops up and I am able to press the button, I am not able to get the edittext field to register the onclicks of the keys thus resulting in the buttons doing nothing. I have pmed Simplicity and was requested by him to post this question in the thread for others in case anyone else runs into this issue.


I have attached both the xml and java file to the post.

Hope someone can help and also hope this problem I ran into will help others if they are stuck at the same place.

Once again a big big big Thanks to SimplicityApks.
Had a look at your class and the xml keyboard layout again and everything seems fine to me so far... Question is how you implemented the keyboard in your activity layout and what happens when you register your text field in the onCreate(). It would be helpful if you could show us these parts of your code.

Other than that, does your onKey() method in the CustomKeyboard get called when you press a key? (Put a Log.d(..) statement or debug stopped in there to find out)
 

kva123

Member
Dec 18, 2010
28
3
0
Had a look at your class and the xml keyboard layout again and everything seems fine to me so far... Question is how you implemented the keyboard in your activity layout and what happens when you register your text field in the onCreate(). It would be helpful if you could show us these parts of your code.

Other than that, does your onKey() method in the CustomKeyboard get called when you press a key? (Put a Log.d(..) statement or debug stopped in there to find out)
Hey sorry for the late response I just figured out what the problem was but now I have no idea how to fix it. The problem is here

Code:
  <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="10dp"
        android:padding="10dp"
        android:descendantFocusability="beforeDescendants" 


        [COLOR="Red"]android:focusableInTouchMode="true" //This Right here is the problem[/COLOR]


        android:weightSum="6" >

        <TextView
            android:id="@+id/billtotalTV"
            android:layout_width="0dp"
            android:paddingLeft="25dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:text="Bill Amount:"
            android:textColor="#B34F6675"
            android:textSize="25sp" />

        <EditText
            android:id="@+id/et"
            android:layout_width="0dp"
            android:paddingRight="25dp"
            android:layout_height="wrap_content"
            android:hint="Enter Total"
            android:gravity="center_horizontal"
            android:textColor="#049C7A"
            android:textColorHint="#B3049C7A"
            android:inputType="numberDecimal"
            android:imeOptions="actionDone"
            android:maxLength="7"
            android:textSize="30sp"
            android:layout_weight="3"/>


        </LinearLayout>
The Reason I have that is because I am trying to avoid my app from setting my EditText as a focus as soon as the activity starts. As far as I am aware I do not know of any other methods that can work around that. Let me know what you think I should do.
 

SimplicityApks

Senior Member
May 26, 2013
354
344
0
Aachen
Hey sorry for the late response I just figured out what the problem was but now I have no idea how to fix it. The problem is here

Code:
  <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="10dp"
        android:padding="10dp"
        android:descendantFocusability="beforeDescendants" 


        [COLOR="Red"]android:focusableInTouchMode="true" //This Right here is the problem[/COLOR]


        android:weightSum="6" >

        <TextView
            android:id="@+id/billtotalTV"
            android:layout_width="0dp"
            android:paddingLeft="25dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:text="Bill Amount:"
            android:textColor="#B34F6675"
            android:textSize="25sp" />

        <EditText
            android:id="@+id/et"
            android:layout_width="0dp"
            android:paddingRight="25dp"
            android:layout_height="wrap_content"
            android:hint="Enter Total"
            android:gravity="center_horizontal"
            android:textColor="#049C7A"
            android:textColorHint="#B3049C7A"
            android:inputType="numberDecimal"
            android:imeOptions="actionDone"
            android:maxLength="7"
            android:textSize="30sp"
            android:layout_weight="3"/>


        </LinearLayout>
The Reason I have that is because I am trying to avoid my app from setting my EditText as a focus as soon as the activity starts. As far as I am aware I do not know of any other methods that can work around that. Let me know what you think I should do.
So you mean it works perfectly without the focusableInTouchMode="true"? Strange... Then just leave the focus there and hide the softkeyboard in your onCreate() or is there any other reason you don't to have it in focus except for the soft keyboard popping up? (Then set the focus to another view might be the easiest ;) ).
 

kva123

Member
Dec 18, 2010
28
3
0
So you mean it works perfectly without the focusableInTouchMode="true"? Strange... Then just leave the focus there and hide the softkeyboard in your onCreate() or is there any other reason you don't to have it in focus except for the soft keyboard popping up? (Then set the focus to another view might be the easiest ;) ).

I tried hiding the softkeyboard but for some reason it wont hide it just keeps popping up. And he main reason I do not want a focus is because I have a drawerlayout on the app and it contains 3 edit texts so everytime I open the drawer layout it invokes the keyboard to pop up and it selects the edit text which I do not want because its a feature where users may customize the value which they dont need to if they dont want too. As of setting focus to another view I believe I tried that but the edit text still receives the focus for some reason. Mind giving me an example of setting focus on something else? So i can make sure I am doing it right. Maybe a Linear or Relative Layout .


I just tried to hide the keyboard and just realized I am already hiding the keyboard but I am only hiding the default keyboard not the custom keyboard. So my question for you would be how would I hide the Custom Keyboard from showing oncreate?(tried this but no luck customKeyboard.hideCustomKeyboard(); ) it still shows but it does work because i tried it with an onlclick just not working on start. Not sure if you need to edit the customkeyboard java file. If you want I can post the test code im working with right now if you dont mind looking at it.
 
Last edited: