Yakov Yakov - 2 months ago 14
Android Question

keyBackground for special keys - android keyboard

I develop Android keyboard based on the soft keyboard. Now to design the keyboard used in selector and changed the keybackgroung Now everything works except the single keys and active they appear as standard keys: (

This is my slector code:

<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_single="true" android:state_pressed="true" android:drawable="@drawable/btn_keyboard_key_dark_pressed_holo" />
<item android:state_single="true" android:drawable="@drawable/btn_keyboard_key_dark_normal_holo" />
<item android:state_active="true" android:state_pressed="true" android:drawable="@drawable/btn_keyboard_key_dark_pressed_holo" />
<item android:state_active="true" android:drawable="@drawable/btn_keyboard_key_dark_active_holo" />
<item android:state_checkable="true" android:state_checked="true" android:state_pressed="true" android:drawable="@drawable/btn_keyboard_key_dark_pressed_on_holo" />
<item android:state_checkable="true" android:state_pressed="true" android:drawable="@drawable/btn_keyboard_key_dark_pressed_off_holo" />
<item android:state_checkable="true" android:state_checked="true" android:drawable="@drawable/btn_keyboard_key_dark_normal_on_holo" />
<item android:state_checkable="true" android:drawable="@drawable/btn_keyboard_key_dark_normal_off_holo" />
<item android:state_pressed="true" android:drawable="@drawable/btn_keyboard_key_light_pressed_holo" />
<item android:drawable="@drawable/btn_keyboard_key_light_normal_holo" />
</selector>

Answer

Solution:

After many attempts, I found the solution to the problem! On the original Keyboard class the Single/Active Drawable State is indefinite. So what we need to do is to override the class.

How to do it? If your keyboard is based on SoftKeyboard we have a LatinKeyboard class that extends Keyboard. If you don't have this class, create it! Now on this class we have a LatinKey static class that extends Keyboard.Key .

Now, how to code: this is LatinKey class code:

static class LatinKey extends Key {

        public LatinKey(Resources res, Row parent, int x, int y, XmlResourceParser parser) {
            super(res, parent, x, y, parser);
        }

        private final static int[] KEY_STATE_NORMAL_ON = { 
            android.R.attr.state_checkable, 
            android.R.attr.state_checked
        };

        private final static int[] KEY_STATE_PRESSED_ON = { 
            android.R.attr.state_pressed, 
            android.R.attr.state_checkable, 
            android.R.attr.state_checked 
        };

        private final static int[] KEY_STATE_NORMAL_OFF = { 
            android.R.attr.state_checkable 
        };

        private final static int[] KEY_STATE_PRESSED_OFF = { 
            android.R.attr.state_pressed, 
            android.R.attr.state_checkable 
        };

        private final static int[] KEY_STATE_FUNCTION = { 
            android.R.attr.state_single
        };

        private final static int[] KEY_STATE_FUNCTION_PRESSED = { 
            android.R.attr.state_pressed, 
            android.R.attr.state_single
        };

        private final static int[] KEY_STATE_NORMAL = {
        };

        private final static int[] KEY_STATE_PRESSED = {
            android.R.attr.state_pressed
        };

        @Override
        public int[] getCurrentDrawableState() {
            int[] states = KEY_STATE_NORMAL;

            if (on) {
                if (pressed) {
                    states = KEY_STATE_PRESSED_ON;
                } else {
                    states = KEY_STATE_NORMAL_ON;
                }
            } else {
                if (sticky) {
                    if (pressed) {
                        states = KEY_STATE_PRESSED_OFF;
                    } else {
                        states = KEY_STATE_NORMAL_OFF;
                    }
                } else if(modifier){
                    if (pressed) {
                        states = KEY_STATE_FUNCTION_PRESSED;
                    } else {
                        states = KEY_STATE_FUNCTION;
                    }
                } else {
                    if (pressed) {
                        states = KEY_STATE_PRESSED;
                    }
                }
            }
            return states;
        }
    }

I add STATE_FUNCTION and STATE_FUNCTION_PRESSED in addition to another original STATE. And then I overrided the getCurrentDrawableState method and added new states to the method. Afterwards, if the key is modifier it will be STATE_FUNCTION and use state_single from the drawableStateList.

Now on the LatinKeyboard:

public class LatinKeyboard extends Keyboard {

        public Skeyboard(Context context, int xmlLayoutResId) {
            super(context, xmlLayoutResId);
            // TODO Auto-generated constructor stub
        }

        public Skeyboard(Context context, int layoutTemplateResId, 
                CharSequence characters, int columns, int horizontalPadding) {
            super(context, layoutTemplateResId, characters, columns, horizontalPadding);
        }

        @Override
        protected Key createKeyFromXml(Resources res, Row parent, int x, int y, 
                XmlResourceParser parser) {
            Key key = new LatinKey(res, parent, x, y, parser);
            return key;
        }
   static class LatinKey extends Keyboard.Key {
     //LatinKey code...
   }
}

We overrided the createKeyFromXml and returned the new LatinKey, now on the main keyboard class use the new LatinKeyboard class and enjoy :)

Comments