I've been trying to find a way to implement ripple effect on KeyboardView keys when they are pressed. Sounds simple enough, but I've tried all the ways of adding ripple that work on other types of view (listview, button, etc) with no success at all.
My aim is to create a numeric keypad that looks like the keypad in the stock Calculator app which comes by default in Lollipop OS:
There's a similar calculator app in GitHub (https://github.com/numixproject/com.numix.calculator) which has a ripple effect on its keypad, but as I read the code seems like it's using buttons for the numeric keys instead of a KeyboardView.
I hope ripple effect is doable with KeyboardView, as my app already has the implementation of a custom numeric keyboard using KeyboardView, and I'd hate to have to change it to use buttons.
I've tried adding the ripple as the keyBackground
attribute from the style like this:
<android.inputmethodservice.KeyboardView
android:id="@+id/numeric_keypad"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusable="true"
android:focusableInTouchMode="true"
style="@style/my_numeric_keypad" />
Then in themes.xml:
<style name="my_numeric_keypad">
<item name="android:keyTextSize">30dp</item>
<item name="android:fontFamily">roboto</item>
<item name="android:keyBackground">@drawable/numeric_keypad_ripple</item>
<item name="android:keyTextColor">@android:color/white</item>
</style>
and then numeric_keypad_ripple.xml in drawable-v21 folder:
<?xml version="1.0" encoding="UTF-8" ?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:drawable="@drawable/numeric_keypad_states"/>
</ripple>
numeric_keypad_states.xml is the old selector with the pressed state (it used to be declared straight as the keyBackground
attribute):
<?xml version="1.0" encoding="UTF-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/numeric_keypad_pressed" />
<item android:drawable="@drawable/numeric_keypad_normal" />
</selector>
numeric_keypad_pressed.xml and numeric_keypad_normal.xml are just the drawable with the color for each specific state, like this (both are exactly the same, just differ in the color attribute):
<?xml version="1.0" encoding="UTF-8" ?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<solid android:color="@color/numeric_keypad_pressed_color"/>
</shape>
</item>
</layer-list>
I thought my approach above would work; but it doesn't. In my Lollipop device, when I press the keypad it just shows the normal pressed color without any ripple at all, no difference to my old implementation without the ripple. I've tried removing the layer because I thought it's somehow overlapping with the ripple, but still doesn't work. Adding mask to the ripple also doesn't work.
I've also tried using the rippledrawable as the pressed state drawable in the selector instead of wrapping the selector, but it's still not working. Also tried using ?android:attr/selectableItemBackground
instead of a rippledrawable but also doesn't work.
And oh, I'm actually developing the app on Xamarin instead of native Android, but that shouldn't make any difference I suppose.
Just answering my own question so it may help others.
As @alanv mentioned in his comment, Ripples won't work in KeyboardView because of its different way of handling rendering and touch interaction.
So the answer is no, it's not possible to use ripple effect in Android KeyboardView.
Hope this can save others from wasting time trying to figure out how to add ripple to KeyboardView :)