Search code examples
androiddrawableandroid-drawableandroid-4.2-jelly-bean

Using default ShapeDrawable in a StateListDrawable in Android 4.2


Anyone else got problems using a new ShapeDrawable() in a StateListDrawable in android 4.2? I used to do this:

ShapeDrawable bg = new ShapeDrawable();    //default Ctor
ShapeDrawable hl = new ShapeDrawable();
hl.getPaint().setColor(color1);
bg.getPaint().setColor(color2);

StateListDrawable s1 = new StateListDrawable();
s1.addState(new int[]{android.R.attr.state_pressed}, hl);
s1.addState(new int[]{}, bg);

But this doesn't work anymore in Android 4.2, throwing a nullpointerexception :

java.lang.NullPointerException
at android.graphics.drawable.ShapeDrawable.mutate(ShapeDrawable.java:387)
at android.graphics.drawable.DrawableContainer.selectDrawable(DrawableContainer.java:315)
at android.graphics.drawable.StateListDrawable.onStateChange(StateListDrawable.java:106)
at android.graphics.drawable.StateListDrawable.addState(StateListDrawable.java:89)

I fixed the issue by changing the constructor of my ShapeDrawable:

ShapeDrawable bg = new ShapeDrawable(new RectShape());
ShapeDrawable hl = new ShapeDrawable(new RectShape());

Now this works great, but I would like to know why this didn't work with the default constructor =)

Thank you for your time :)


Solution

  • the DrawableContainer.selectDrawable() realization has changed in Android 4.2 and the ShapeDrawable must use construct with args.

    If you use default constructor ,when invoke mutate() mShape is null ,so mShape.clone() will throw CloneNotSupportedException and return null. so you get a NullPointerException.