1

So, according to the Android documentation, Resources.getDrawable() has a known bug for OS versions before Jelly Bean, where aliased drawables would not be resolved with the correct density (so a 100px image in drawable-hdpi gets upscaled to 150px on an HDPI device):

Note: Prior to JELLY_BEAN, this function would not correctly retrieve the final configuration density when the resource ID passed here is an alias to another Drawable resource. This means that if the density configuration of the alias resource is different than the actual resource, the density of the returned Drawable would be incorrect, resulting in bad scaling. To work around this, you can instead retrieve the Drawable through TypedArray.getDrawable. Use Context.obtainStyledAttributes with an array containing the resource ID of interest to create the TypedArray.

However, I've not been able to actually resolve a Drawable using the instructions specified. A utility method that I've written:

@NonNull
public static Drawable resolveDrawableAlias(@NonNull Context ctx, @DrawableRes int drawableResource) {
    final TypedArray a = ctx.obtainStyledAttributes(new int[] { drawableResource });
    final Drawable result = a.getDrawable(0);
    a.recycle();
    return result;
}

always returns null when I'm passing in a resource ID for a drawable alias, which I've defined in res/values/drawables.xml as:

<item name="my_drawable" type="drawable">@drawable/my_drawable_variation</item>

Is there something I'm missing here, or some other workaround?

EDIT: I've added a solution below.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • 2
    It may be that by "resource alias" here, they meant ``, per: http://developer.android.com/guide/topics/resources/providing-resources.html#AliasResources Also, you don't pass in the IDs of a drawable resource to `obtainStyledAttributes`, but rather the IDs of attributes: http://developer.android.com/reference/android/content/res/Resources.Theme.html#obtainStyledAttributes%28int[]%29 – CommonsWare Sep 29 '14 at 18:24
  • @CommonsWare Ah, hmm. That could be. If so, there may be no good workaround for what I need (I can't use a bitmap alias since the target is another Drawable -- not a bitmap directly). – Kevin Coppock Sep 29 '14 at 18:26

1 Answers1

1

Alright, I've found the following solution which seems to do the trick:

/**
 * Method used as a workaround for a known bug in 
 * {@link android.content.res.Resources#getDrawable(int)}
 * where the density is not properly resolved for Drawable aliases 
 * on OS versions before Jelly Bean.
 *
 * @param ctx a context for resources
 * @param drawableResource the resource ID of the drawable to retrieve
 *
 * @return the Drawable referenced by drawableResource
 */
@NonNull
public static Drawable resolveDrawableAlias(@NonNull Context ctx, @DrawableRes int drawableResource) {
    final TypedValue value = new TypedValue();

    // Read the resource into a TypedValue instance, passing true
    // to resolve all intermediate references
    ctx.getResources().getValue(drawableResource, value, true);
    return ctx.getResources().getDrawable(value.resourceId);
}
Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274