Drawable 自定义颜##
如何得到一个Drawable?
举例:资源文件夹下:
this: 上下文
ResId:资源id R.drawable.c ==> 资源文件夹下的图片路径
Drawable drawable = this.getResources().getDrawable(ResId);
TextView textview = new TextView(this);
textview.setsetBackgroundDrawable(drawable);
上面代码就是 为textview(Imageview)设置一个背景图片;
但我想自定义 图片背景颜色怎么办?
这时就用到 **DrawableCompat** 这个类,它可以 上下兼容
Drawable wrapdrawable = DrawableCompat.wrap(drawable);
DrawableCompat.setTintList(wrapdrawable,ColorStateList.valueOf(Color.parseColor(piccolor)));
这样就可以随心所遇的为Drawable 着色了
下面是和 drawable 相关的工具类,有兴趣的小伙伴可以尝试下里面的方法
public class ThemeUtils {
private static final ThreadLocal<TypedValue> TL_TYPED_VALUE = new ThreadLocal<>();
public static final int[] DISABLED_STATE_SET = new int[]{-android.R.attr.state_enabled};
public static final int[] ENABLED_STATE_SET = new int[]{android.R.attr.state_enabled};
public static final int[] FOCUSED_STATE_SET = new int[]{android.R.attr.state_focused};
public static final int[] ACTIVATED_STATE_SET = new int[]{android.R.attr.state_activated};
public static final int[] PRESSED_STATE_SET = new int[]{android.R.attr.state_pressed};
public static final int[] CHECKED_STATE_SET = new int[]{android.R.attr.state_checked};
public static final int[] SELECTED_STATE_SET = new int[]{android.R.attr.state_selected};
public static final int[] EMPTY_STATE_SET = new int[0];
private static final int[] TEMP_ARRAY = new int[1];
public static Drawable tintDrawable(Drawable drawable, @ColorInt int color, PorterDuff.Mode mode) {
if (drawable == null) return null;
Drawable wrapper = DrawableCompat.wrap(drawable.mutate());
DrawableCompat.setTint(wrapper, color);
DrawableCompat.setTintMode(drawable, mode);
return wrapper;
}
public static Drawable tintDrawable(Context context, @DrawableRes int resId, @ColorRes int colorId) {
if (resId <= 0 || colorId <= 0) return null;
Drawable drawable = context.getResources().getDrawable(resId);
return tintDrawableByColorId(context, drawable, colorId);
}
public static Drawable tintDrawable(Drawable drawable, @ColorInt int color) {
return tintDrawable(drawable, color, PorterDuff.Mode.SRC_IN);
}
public static Drawable tintDrawableByDrawableId(Context context, @DrawableRes int resId, @ColorInt int color) {
if (resId <= 0) return null;
Drawable drawable = context.getResources().getDrawable(resId);
return tintDrawable(drawable, color);
}
public static Drawable tintDrawableByColorId(Context context, Drawable drawable, @ColorRes int colorId) {
if (drawable == null) return null;
if (colorId <= 0) return drawable;
return tintDrawable(drawable, replaceColor(context, context.getResources().getColor(colorId)));
}
public static Drawable tintDrawable(Drawable drawable, ColorStateList cls, PorterDuff.Mode mode) {
if (drawable == null) return null;
Drawable wrapper = DrawableCompat.wrap(drawable.mutate());
DrawableCompat.setTintList(wrapper, cls);
DrawableCompat.setTintMode(drawable, mode);
return wrapper;
}
public static Drawable tintDrawableByColorList(Context context, Drawable drawable, @ColorRes int colorListId, PorterDuff.Mode mode) {
if (drawable == null) return null;
if (colorListId <= 0) return drawable;
return tintDrawable(drawable, TintManager.get(context).getColorStateList(colorListId), mode == null ? PorterDuff.Mode.SRC_IN : mode);
}
public static
@ColorInt
int getColorById(Context context, @ColorRes int colorId) {
return replaceColorById(context, colorId);
}
public static
@ColorInt
int getColor(Context context, @ColorInt int color) {
return replaceColor(context, color);
}
public static
@ColorInt
int getThemeAttrColor(Context context, @AttrRes int attr) {
return hasThemeAttr(context, attr) ? replaceColorById(context, getThemeAttrId(context, attr)) : Color.TRANSPARENT;
}
static int getThemeAttrColor(Context context, @AttrRes int attr, float alpha) {
final int color = getThemeAttrColor(context, attr);
final int originalAlpha = Color.alpha(color);
return ColorUtils.setAlphaComponent(color, Math.round(originalAlpha * alpha));
}
public static ColorStateList getThemeAttrColorStateList(Context context, @AttrRes int attr) {
TEMP_ARRAY[0] = attr;
TypedArray a = context.obtainStyledAttributes(null, TEMP_ARRAY);
try {
return a.getColorStateList(0);
} finally {
a.recycle();
}
}
public static int getDisabledThemeAttrColor(Context context, @AttrRes int attr) {
final ColorStateList csl = getThemeAttrColorStateList(context, attr);
if (csl != null && csl.isStateful()) {
// If the CSL is stateful, we'll assume it has a disabled state and use it
return csl.getColorForState(DISABLED_STATE_SET, csl.getDefaultColor());
} else {
// Else, we'll generate the color using disabledAlpha from the theme
final TypedValue tv = getTypedValue();
// Now retrieve the disabledAlpha value from the theme
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, tv, true);
final float disabledAlpha = tv.getFloat();
return getThemeAttrColor(context, attr, disabledAlpha);
}
}
public static int getThemeAttrId(Context context, @AttrRes int attr) {
TEMP_ARRAY[0] = attr;
TypedArray a = context.obtainStyledAttributes(null, TEMP_ARRAY);
try {
return a.getResourceId(0, 0);
} finally {
a.recycle();
}
}
public static int getThemeAttrId(Context context, AttributeSet attrs, @AttrRes int attr) {
TEMP_ARRAY[0] = attr;
TypedArray a = context.obtainStyledAttributes(attrs, TEMP_ARRAY);
try {
return a.getResourceId(0, 0);
} finally {
a.recycle();
}
}
public static boolean getThemeAttrBoolean(Context context, @AttrRes int attr) {
TEMP_ARRAY[0] = attr;
TypedArray a = context.obtainStyledAttributes(null, TEMP_ARRAY);
try {
return a.getBoolean(0, false);
} finally {
a.recycle();
}
}
public static boolean hasThemeAttr(Context context, @AttrRes int attr) {
TEMP_ARRAY[0] = attr;
TypedArray a = context.obtainStyledAttributes(null, TEMP_ARRAY);
try {
return a.hasValue(0);
} finally {
a.recycle();
}
}
public static int getThemeAttrDimensionPixelSize(Context context, @AttrRes int attr) {
TEMP_ARRAY[0] = attr;
TypedArray a = context.obtainStyledAttributes(null, TEMP_ARRAY);
try {
return a.getDimensionPixelSize(0, 0);
} finally {
a.recycle();
}
}
private static TypedValue getTypedValue() {
TypedValue typedValue = TL_TYPED_VALUE.get();
if (typedValue == null) {
typedValue = new TypedValue();
TL_TYPED_VALUE.set(typedValue);
}
return typedValue;
}
// skip animated-selector when android version is 5.0.x
private static boolean isSkipAnimatedSelector = false;
private static boolean hasRecordedVersion = false;
public static boolean isSkipAnimatedSelector() {
if (!hasRecordedVersion) {
final String sdkVersion = Build.VERSION.RELEASE;
isSkipAnimatedSelector = !Build.UNKNOWN.equals(sdkVersion) && "5.0".compareTo(sdkVersion) <= 0 && "5.1".compareTo(sdkVersion) > 0;
hasRecordedVersion = true;
}
return isSkipAnimatedSelector;
}
public static boolean containsNinePatch(Drawable drawable) {
drawable = getWrapperDrawable(drawable);
if (drawable instanceof NinePatchDrawable
|| drawable instanceof InsetDrawable
|| drawable instanceof LayerDrawable) {
return true;
} else if (drawable instanceof StateListDrawable) {
final DrawableContainer.DrawableContainerState containerState = ((DrawableContainer.DrawableContainerState) drawable.getConstantState());
//can't get containState from drawable which is containing DrawableWrapperDonut
//https://code.google.com/p/android/issues/detail?id=169920
if (containerState == null) {
return true;
}
for (Drawable dr : containerState.getChildren()) {
dr = getWrapperDrawable(dr);
if (dr instanceof NinePatchDrawable
|| dr instanceof InsetDrawable
|| dr instanceof LayerDrawable) {
return true;
}
}
}
return false;
}
public static Drawable getWrapperDrawable(Drawable drawable) {
if (drawable instanceof android.support.v4.graphics.drawable.DrawableWrapper) {
return ((android.support.v4.graphics.drawable.DrawableWrapper) drawable).getWrappedDrawable();
} else if (drawable instanceof android.support.v7.graphics.drawable.DrawableWrapper) {
return ((android.support.v7.graphics.drawable.DrawableWrapper) drawable).getWrappedDrawable();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && drawable instanceof android.graphics.drawable.DrawableWrapper) {
return ((android.graphics.drawable.DrawableWrapper) drawable).getDrawable();
}
return drawable;
}
public static Activity getWrapperActivity(Context context) {
if (context instanceof Activity) {
return (Activity) context;
} else if (context instanceof ContextWrapper) {
return getWrapperActivity(((ContextWrapper) context).getBaseContext());
}
return null;
}
public static ContextWrapper getWrapperContext(Context context, @StyleRes int themeId) {
if (context == null) return null;
return new ContextThemeWrapper(context, themeId);
}
public static Resources updateNightMode(Resources resource, boolean on) {
DisplayMetrics dm = resource.getDisplayMetrics();
Configuration config = resource.getConfiguration();
final int uiModeNightMaskOrigin = config.uiMode &= ~Configuration.UI_MODE_TYPE_MASK;
final int uiModeNightMaskNew = on ? Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO;
if (uiModeNightMaskOrigin != uiModeNightMaskNew) {
config.uiMode &= ~Configuration.UI_MODE_NIGHT_MASK;
config.uiMode |= uiModeNightMaskNew;
resource.updateConfiguration(config, dm);
}
return resource;
}
static TintInfo parseColorStateList(ColorStateList origin) {
if (origin == null) return null;
boolean hasDisable = false;
int originDefaultColor = origin.getDefaultColor();
LinkedList<int[]> stateList = new LinkedList<>();
LinkedList<Integer> colorList = new LinkedList<>();
int disableColor = origin.getColorForState(DISABLED_STATE_SET, 0);
if (disableColor != originDefaultColor) {
hasDisable = true;
stateList.add(DISABLED_STATE_SET);
colorList.add(disableColor);
}
int pressedColor = origin.getColorForState(wrapState(hasDisable, PRESSED_STATE_SET), 0);
if (pressedColor != originDefaultColor) {
stateList.add(PRESSED_STATE_SET);
colorList.add(pressedColor);
}
int focusColor = origin.getColorForState(wrapState(hasDisable, FOCUSED_STATE_SET), 0);
if (focusColor != originDefaultColor) {
stateList.add(FOCUSED_STATE_SET);
colorList.add(focusColor);
}
int checkedColor = origin.getColorForState(wrapState(hasDisable, CHECKED_STATE_SET), 0);
if (checkedColor != originDefaultColor) {
stateList.add(CHECKED_STATE_SET);
colorList.add(checkedColor);
}
int selectedColor = origin.getColorForState(wrapState(hasDisable, SELECTED_STATE_SET), 0);
if (selectedColor != originDefaultColor) {
stateList.add(SELECTED_STATE_SET);
colorList.add(selectedColor);
}
int normalColor = origin.getColorForState(wrapState(hasDisable, EMPTY_STATE_SET), 0);
if (normalColor != 0) {
stateList.add(EMPTY_STATE_SET);
colorList.add(normalColor);
}
if (colorList.size() > 1) {
return new TintInfo(stateList, colorList);
} else {
return null;
}
}
private static int[] wrapState(boolean hasDisable, int[] targetState) {
return targetState.length > 0
? (hasDisable ? new int[]{ENABLED_STATE_SET[0], targetState[0]} : targetState)
: (hasDisable ? ENABLED_STATE_SET : targetState);
}
public static ColorStateList getThemeColorStateList(Context context, ColorStateList origin) {
if (origin == null) return null;
if (origin.isStateful()) {
TintInfo tintInfo = parseColorStateList(origin);
if (tintInfo == null || tintInfo.isInvalid()) {
return origin;
}
int[] newColors;
int[][] newStates;
int index = 0;
boolean hasDisableColor = StateSet.stateSetMatches(tintInfo.mTintStates[0], DISABLED_STATE_SET);
if (!hasDisableColor) {
newStates = new int[tintInfo.mTintStates.length + 1][];
newColors = new int[tintInfo.mTintStates.length + 1];
newStates[index] = DISABLED_STATE_SET;
newColors[index] = getDisabledThemeAttrColor(context, R.attr.themeColorSecondary);
index++;
} else {
newStates = new int[tintInfo.mTintStates.length][];
newColors = new int[tintInfo.mTintStates.length];
}
for (int i = 0; i < tintInfo.mTintStates.length; i++) {
newStates[index] = tintInfo.mTintStates[i];
newColors[index] = replaceColor(context, tintInfo.mTintColors[i]);
index++;
}
return new ColorStateList(newStates, newColors);
}
return ColorStateList.valueOf(replaceColor(context, origin.getDefaultColor()));
}
public static ColorStateList getThemeColorStateList(Context context, @ColorRes int colorId) {
return ColorStateListUtils.createColorStateList(context, colorId);
}
public static void refreshUI(Context context) {
refreshUI(context, null);
}
public static void refreshUI(Context context, ExtraRefreshable extraRefreshable) {
TintManager.clearTintCache();
Activity activity = getWrapperActivity(context);
if (activity != null) {
if (extraRefreshable != null) {
extraRefreshable.refreshGlobal(activity);
}
View rootView = activity.getWindow().getDecorView().findViewById(android.R.id.content);
refreshView(rootView, extraRefreshable);
}
}
private static Field mRecycler;
private static Method mClearMethod;
private static void refreshView(View view, ExtraRefreshable extraRefreshable) {
if (view == null) return;
view.destroyDrawingCache();
if (view instanceof Tintable) {
((Tintable) view).tint();
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
refreshView(((ViewGroup) view).getChildAt(i), extraRefreshable);
}
}
} else {
if (extraRefreshable != null) {
extraRefreshable.refreshSpecificView(view);
}
if (view instanceof AbsListView) {
ListAdapter adapter = ((AbsListView) view).getAdapter();
while (adapter instanceof WrapperListAdapter) {
adapter = ((WrapperListAdapter) adapter).getWrappedAdapter();
}
if (adapter instanceof BaseAdapter) {
((BaseAdapter) adapter).notifyDataSetChanged();
}
}
if (view instanceof RecyclerView) {
try {
if (mRecycler == null) {
mRecycler = RecyclerView.class.getDeclaredField("mRecycler");
mRecycler.setAccessible(true);
}
if (mClearMethod == null) {
mClearMethod = Class.forName("android.support.v7.widget.RecyclerView$Recycler")
.getDeclaredMethod("clear");
mClearMethod.setAccessible(true);
}
mClearMethod.invoke(mRecycler.get(view));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
((RecyclerView) view).getRecycledViewPool().clear();
((RecyclerView) view).invalidateItemDecorations();
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
refreshView(((ViewGroup) view).getChildAt(i), extraRefreshable);
}
}
}
}
public interface ExtraRefreshable {
void refreshGlobal(Activity activity);
void refreshSpecificView(View view);
}
public static switchColor mSwitchColor;
public static void setSwitchColor(switchColor switchColor) {
mSwitchColor = switchColor;
}
static
@ColorInt
int replaceColorById(Context context, @ColorRes int colorId) {
return mSwitchColor == null ? Color.TRANSPARENT : mSwitchColor.replaceColorById(context, colorId);
}
static
@ColorInt
int replaceColor(Context context, @ColorInt int color) {
return mSwitchColor == null ? Color.TRANSPARENT : mSwitchColor.replaceColor(context, color);
}
public interface switchColor {
@ColorInt
int replaceColorById(Context context, @ColorRes int colorId);
@ColorInt
int replaceColor(Context context, @ColorInt int color);
}
}