Skip to content

Instantly share code, notes, and snippets.

@SimoneCasagranda
Created April 30, 2014 21:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SimoneCasagranda/a53f417caa1567d99539 to your computer and use it in GitHub Desktop.
Save SimoneCasagranda/a53f417caa1567d99539 to your computer and use it in GitHub Desktop.
ColorDrawable extension that aims to bring newer features of the ColorDrawable to the older versions of Android like the ones prior than HoneyComb (API LEVEL 11).
package uk.co.enomis.app.compat;
import android.annotation.TargetApi;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.util.Log;
import java.lang.reflect.Field;
/**
* ColorDrawable extension that aims to bring newer features of the ColorDrawable
* to the older versions of Android like the ones prior than HoneyComb (API LEVEL 11).
* <p/>
* Created by Simone Casagranda - 30/04/14
*/
public class ColorDrawableCompat extends ColorDrawable {
/**
* Tag used for logging purposes.
*/
private static final String TAG_LOG = ColorDrawableCompat.class.getName();
public ColorDrawableCompat() {
}
public ColorDrawableCompat(int color) {
super(color);
}
/**
* Gets the drawable's color value.
*
* @return The color to draw, Color.TRANSPARENT will be returned on pre-Honeycomb version if something fails.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public int getColor() {
// Get color is available only on Honeycomb onwards
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
return super.getColor();
} else {
int color = Color.TRANSPARENT;
try {
final Object state = get(this, getClass().getSuperclass().getDeclaredField("mState"));
final Field useColor = state.getClass().getDeclaredField("mUseColor");
final boolean useAccessible = useColor.isAccessible();
if (!useAccessible) {
useColor.setAccessible(true);
}
color = useColor.getInt(state);
if (!useAccessible) {
useColor.setAccessible(false);
}
} catch (Exception e) {
Log.e(TAG_LOG, "Cannot complete getColor() on VERSION_CODE=" + Build.VERSION.SDK_INT, e);
}
return color;
}
}
/**
* Sets the drawable's color value. This action will clobber the results of prior calls to setAlpha(int)
* on this object, which side-affected the underlying color.
* <p/>
* NB: If something fails it will result without any color update.
*
* @param color The color to draw.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void setColor(int color) {
// Set color is available only on Honeycomb onwards
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
super.setColor(color);
} else {
try {
final Object state = get(this, getClass().getSuperclass().getDeclaredField("mState"));
// Getting the required fields and enabling them if needed
final Field baseField = state.getClass().getDeclaredField("mBaseColor");
final boolean baseAccessible = baseField.isAccessible();
if (!baseAccessible) {
baseField.setAccessible(true);
}
final Field useField = state.getClass().getDeclaredField("mUseColor");
final boolean useAccessible = useField.isAccessible();
if (!useAccessible) {
useField.setAccessible(true);
}
// Getting and updating the fields
final int baseColor = baseField.getInt(state);
final int useColor = useField.getInt(state);
if (baseColor != color || useColor != color) {
baseField.setInt(state, color);
useField.setInt(state, color);
invalidateSelf();
}
// Restoring any prior state
if (!baseAccessible) {
baseField.setAccessible(false);
}
if (!useAccessible) {
useField.setAccessible(false);
}
} catch (Exception e) {
Log.e(TAG_LOG, "Cannot complete setColor(" + color + ") on VERSION_CODE=" + Build.VERSION.SDK_INT, e);
}
}
}
/**
* Get the values of a {@link java.lang.reflect.Field}.
*
* @param parent used to get value.
* @param field where the value should be taken.
* @return the value or null if something goes wrong.
*/
private static Object get(Object parent, Field field) {
if (field == null) {
return null;
}
Object value = null;
try {
// Checking the accessibility of the field
boolean accessible = field.isAccessible();
if (!accessible) {
field.setAccessible(true);
value = field.get(parent);
field.setAccessible(false);
} else {
value = field.get(parent);
}
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment