Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement ripple effect in Android KeyboardView?

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:

Stock Lollipop calculator

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.

like image 435
ABVincita Avatar asked Jan 17 '15 13:01

ABVincita


2 Answers

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 :)

like image 111
ABVincita Avatar answered Nov 15 '22 12:11

ABVincita


My response to that is: there is not an already implemented way (in another words: an easy way) to do that. But we are talking about open source technology, so...

If you have some time and patience, you can create a custom KeyboardView from original to redefines the way that default component create its views with a ripple compatible layout.

"If you can't solve a problem, change the problem" (Henry Ford).

like image 20
Renascienza Avatar answered Nov 15 '22 13:11

Renascienza