'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 1:[1]

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..

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Vijay Dhas