Search code examples
androidcustom-keyboard

Custom Keyboard keys background color is not applying in Android


I am Creating custom keyboard. I am using KeyboardView for custom keyboard. I am trying to change the keys background color. While I am setting by xml it is working fine. But When I try with java code it is not working as expected. Here is my code.

@Override
    public void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);

        List<Keyboard.Key> keys = getKeyboard().getKeys();
        for (Keyboard.Key key : keys) {
            if (key.codes[0] == 53) {
//                drawKeyBackground(canvas, key);
                drawKeyBackground(R.drawable.samplekeybackground,canvas,key);
                drawText(canvas, key);
            }
        }

    }


private void drawKeyBackground(int drawableId, Canvas canvas, Keyboard.Key key) {
        Drawable npd = context.getResources().getDrawable(
                drawableId);
        int[] drawableState = key.getCurrentDrawableState();
        if (key.codes[0] != 0) {
            npd.setState(drawableState);
        }
        npd.setBounds(key.x, key.y, key.x + key.width, key.y
                + key.height);
        npd.draw(canvas);
    }

This code is working fine. But I am trying to change samplekeybackground.xml to java code.

public StateListDrawable getSelectorDrawable() {
        StateListDrawable out = new StateListDrawable();
        out.addState(new int[] { android.R.attr.state_pressed }, createDrawable(Color.GREEN));
        out.addState(new int[] { android.R.attr.state_focused }, createDrawable(Color.GREEN));
        out.addState(new int[] { android.R.attr.state_enabled }, createDrawable(Color.BLUE));
        return out;
    }

public GradientDrawable createDrawable(int color) {
    GradientDrawable out = new GradientDrawable();
    out.setShape(GradientDrawable.RECTANGLE);
    out.setGradientType(GradientDrawable.LINEAR_GRADIENT);
    out.setColor(color);
    out.setStroke(2, color);
    out.setCornerRadius(0F);
    return out;
}

Finally call the method by following code:

 private void drawKeyBackground(Canvas canvas, Keyboard.Key key) {
        Drawable npd = getSelectorDrawable();
        int[] drawableState = key.getCurrentDrawableState();
        if (key.codes[0] != 0) {
            npd.setState(drawableState);
        }
        npd.setBounds(key.x, key.y, key.x + key.width, key.y
                + key.height);
        npd.draw(canvas);
    }

But when I click the key pressed_state color is working. But normal state is not working.

sample img

Please help me to resolve this issue.


Solution

  • Gracefully this class solved my issue.

    public class StateDrawableBuilder {
    
        private static final int[] STATE_SELECTED = new int[]{android.R.attr.state_selected};
        private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
        private static final int[] STATE_ENABED = new int[]{android.R.attr.state_enabled};
        private static final int[] STATE_DISABED = new int[]{-android.R.attr.state_enabled};
        private static final int[] STATE_NORMAL = new int[]{};
    
        private Drawable normalDrawable;
        private Drawable selectedDrawable;
        private Drawable pressedDrawable;
        private Drawable disabledDrawable;
    
        public StateDrawableBuilder setNormalDrawable(Drawable normalDrawable) {
            this.normalDrawable = normalDrawable;
            return this;
        }
    
        public StateDrawableBuilder setPressedDrawable(Drawable pressedDrawable) {
            this.pressedDrawable = pressedDrawable;
            return this;
        }
    
        public StateDrawableBuilder setSelectedDrawable(Drawable selectedDrawable) {
            this.selectedDrawable = selectedDrawable;
            return this;
        }
    
        public StateDrawableBuilder setDisabledDrawable(Drawable disabledDrawable) {
            this.disabledDrawable = disabledDrawable;
            return this;
        }
    
        public StateListDrawable build() {
            StateListDrawable stateListDrawable = new StateListDrawable();
            if (this.selectedDrawable != null) {
                stateListDrawable.addState(STATE_SELECTED, this.selectedDrawable);
            }
    
            if (this.pressedDrawable != null) {
                stateListDrawable.addState(STATE_PRESSED, this.pressedDrawable);
            }
    
            if (this.normalDrawable != null) {
                stateListDrawable.addState(STATE_NORMAL, this.normalDrawable);
            }
    
            if (this.disabledDrawable != null) {
                stateListDrawable.addState(STATE_DISABED, this.disabledDrawable);
            }
            return stateListDrawable;
        }
    
        public static Drawable getShapeDrawable(int color,int rad,int border,int borderColor){
            GradientDrawable gradientDrawable = new GradientDrawable();
            gradientDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
            gradientDrawable.setShape(GradientDrawable.RECTANGLE);
            gradientDrawable.setColor(color);
            gradientDrawable.setStroke(border,borderColor);
            return gradientDrawable;
        }
    
        private ShapeDrawable getShapeDrawable(int color,int rad,int border) {
            RoundRectShape roundRectShape = new RoundRectShape(new float[]{
                    rad, rad, rad, rad,
                    rad, rad, rad, rad}, null, null);
            ShapeDrawable shapeDrawable = new ShapeDrawable(roundRectShape);
            shapeDrawable.getPaint().setColor(color);
            shapeDrawable.getPaint().setStrokeWidth(border);
            return shapeDrawable;
        }
    }
    

    and use the builder like following.

    StateListDrawable npd = new StateDrawableBuilder()
                    .setNormalDrawable(StateDrawableBuilder.getShapeDrawable(Color.RED,10,5,Color.BLUE))
                    .setPressedDrawable(StateDrawableBuilder.getShapeDrawable(Color.GREEN,10,5,Color.BLUE))
                    .setSelectedDrawable(StateDrawableBuilder.getShapeDrawable(Color.GREEN,10,5,Color.BLUE))
                    .build();
    

    Now KeyboardView key bg color and focus color is working as expected..