package com.simplecity.amp_library.utils; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Color; import android.support.annotation.ColorInt; import android.support.annotation.FloatRange; import android.view.View; import com.simplecity.amp_library.R; import com.simplecity.amp_library.ShuttleApplication; public class ColorUtils { /** * @return the highlight color for the current theme */ public static int getPrimaryColor() { return SettingsManager.getInstance().getPrimaryColor(ShuttleApplication.getInstance().getResources().getColor(R.color.indigo_500)); } public static int getAccentColor() { if (SettingsManager.getInstance().isAccentColorWhite()) { return getPrimaryColor(); } return SettingsManager.getInstance().getAccentColor(ColorUtils.getDefaultAccentColor(getPrimaryColor())); } public static int getAccentColor(boolean canBeWhite, boolean useAccent) { if (!useAccent && !canBeWhite && SettingsManager.getInstance().isAccentColorWhite()) { return getPrimaryColor(); } return SettingsManager.getInstance().getAccentColor(ColorUtils.getDefaultAccentColor(getPrimaryColor())); } /** * @param context Context * @return an alternative, visible accent color */ public static int getContrastAwareColorAccent(Context context) { Resources res = context.getResources(); int colorAccent = getAccentColor(); int themeType = ThemeUtils.getThemeType(context); if (isAccentColorHighContrast(context)) { if (themeType == ThemeUtils.ThemeType.TYPE_DARK || themeType == ThemeUtils.ThemeType.TYPE_SOLID_DARK || themeType == ThemeUtils.ThemeType.TYPE_SOLID_BLACK) { return android.graphics.Color.WHITE; } else { return res.getColor(R.color.grey_700); } } return colorAccent; } public static boolean isAccentColorHighContrast(Context context) { Resources res = context.getResources(); int colorAccent = getAccentColor(); return colorAccent == res.getColor(R.color.yellow_a100) || colorAccent == res.getColor(R.color.yellow_a200) || colorAccent == res.getColor(R.color.yellow_a400) || colorAccent == res.getColor(R.color.light_green_a100) || colorAccent == res.getColor(R.color.light_green_a200) || colorAccent == res.getColor(R.color.green_a100) || colorAccent == res.getColor(R.color.light_green_a400) || colorAccent == res.getColor(R.color.cyan_a100) || colorAccent == res.getColor(R.color.teal_a100) || colorAccent == res.getColor(R.color.lime_a100) || colorAccent == res.getColor(R.color.lime_a200) || colorAccent == res.getColor(R.color.lime_a400) || colorAccent == res.getColor(R.color.orange_a100); } public static boolean isPrimaryColorLowContrast(Context context) { if (ThemeUtils.getInstance().isThemeDark()) { Resources res = context.getResources(); int primaryColor = getPrimaryColor(); return primaryColor == res.getColor(R.color.blue_grey_900) || primaryColor == res.getColor(R.color.blue_grey_800) || primaryColor == res.getColor(R.color.black) || primaryColor == res.getColor(R.color.grey_900) || primaryColor == res.getColor(R.color.grey_1000) || primaryColor == res.getColor(R.color.grey_1000) || primaryColor == res.getColor(R.color.brown_900) || primaryColor == res.getColor(R.color.teal_900) || primaryColor == res.getColor(R.color.indigo_900) || primaryColor == res.getColor(R.color.deep_purple_900); } return false; } public static int getFloatingActionIconColor(Context context) { Resources res = context.getResources(); if (isAccentColorHighContrast(context)) { return res.getColor(R.color.grey_700); } return android.graphics.Color.WHITE; } public static int getAccentColorSensitiveTextColor(Context context) { if (isAccentColorHighContrast(context)) { return context.getResources().getColor(R.color.grey_700); } else { return context.getResources().getColor(android.R.color.primary_text_dark); } } public static int getPrimaryColorDark(Context context) { int primaryColor = getPrimaryColor(); return ColorUtils.getColorDark(primaryColor); } public static int getTextColorPrimary() { if (ThemeUtils.getInstance().themeType == ThemeUtils.ThemeType.TYPE_LIGHT || ThemeUtils.getInstance().themeType == ThemeUtils.ThemeType.TYPE_SOLID_LIGHT) { return Color.BLACK; } else { return Color.WHITE; } } @ColorInt public static int shiftColor(@ColorInt int color, @FloatRange(from = 0.0f, to = 2.0f) float by) { if (by == 1f) return color; float[] hsv = new float[3]; Color.colorToHSV(color, hsv); hsv[2] *= by; // value component return Color.HSVToColor(hsv); } public static int getColorDark(int colorPrimary) { if (colorPrimary == Color.BLACK) { return Color.BLACK; } return shiftColor(colorPrimary, 0.85f); } public static int adjustAlpha(int color, float factor) { int alpha = Math.round(Color.alpha(color) * factor); int red = Color.red(color); int green = Color.green(color); int blue = Color.blue(color); return Color.argb(alpha, red, green, blue); } /** * Returns darker version of specified <code>color</code>. */ public static int darkerise(int color, float factor) { int a = Color.alpha(color); int r = Color.red(color); int g = Color.green(color); int b = Color.blue(color); return Color.argb(a, Math.max((int) (r * factor), 0), Math.max((int) (g * factor), 0), Math.max((int) (b * factor), 0)); } public static int getDefaultAccentColor(int color) { Resources res = ShuttleApplication.getInstance().getResources(); if (color == res.getColor(R.color.red_400) || color == res.getColor(R.color.red_500) || color == res.getColor(R.color.red_600)) { return res.getColor(R.color.blue_a200); } if (color == res.getColor(R.color.pink_400) || color == res.getColor(R.color.pink_500) || color == res.getColor(R.color.pink_600)) { return res.getColor(R.color.yellow_a400); } if (color == res.getColor(R.color.purple_400) || color == res.getColor(R.color.purple_500) || color == res.getColor(R.color.purple_600)) { return res.getColor(R.color.yellow_a200); } if (color == res.getColor(R.color.indigo_400) || color == res.getColor(R.color.indigo_500) | color == res.getColor(R.color.indigo_600)) { return res.getColor(R.color.pink_a400); } if (color == res.getColor(R.color.blue_400) || color == res.getColor(R.color.blue_500) || color == res.getColor(R.color.blue_600)) { return res.getColor(R.color.light_blue_a400); } if (color == res.getColor(R.color.light_blue_400) || color == res.getColor(R.color.light_blue_500) || color == res.getColor(R.color.light_blue_600)) { return res.getColor(R.color.deep_purple_a200); } if (color == res.getColor(R.color.cyan_400) || color == res.getColor(R.color.cyan_500) || color == res.getColor(R.color.cyan_600)) { return res.getColor(R.color.deep_purple_a200); } if (color == res.getColor(R.color.teal_400) || color == res.getColor(R.color.teal_500) || color == res.getColor(R.color.teal_600)) { return res.getColor(R.color.light_blue_a200); } if (color == res.getColor(R.color.green_400) || color == res.getColor(R.color.green_500) || color == res.getColor(R.color.green_600)) { return res.getColor(R.color.orange_a200); } if (color == res.getColor(R.color.orange_400) || color == res.getColor(R.color.orange_500) || color == res.getColor(R.color.orange_600)) { return res.getColor(R.color.purple_a200); } if (color == res.getColor(R.color.grey_400) || color == res.getColor(R.color.grey_500) || color == res.getColor(R.color.grey_600)) { return res.getColor(R.color.pink_a200); } if (color == res.getColor(R.color.blue_grey_900) || color == res.getColor(R.color.blue_grey_800 )) { return res.getColor(R.color.cyan_a700); } return color; } public static void startBackgroundTransition(final View view, int colorFrom, int colorTo) { ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); colorAnimation.setDuration(350); colorAnimation.addUpdateListener(animator -> view.setBackgroundColor((Integer) animator.getAnimatedValue())); colorAnimation.start(); } public static ColorStateList getDefaultColorStateList() { ColorStateList colorStateList; /** * Generate the default color state list which uses the colorControl attributes. * Order is important here. The default enabled state needs to go at the bottom. */ final int accentColor = ColorUtils.getAccentColor(); final int[][] states = new int[7][]; final int[] colors = new int[7]; int i = 0; // Disabled state states[i] = new int[]{-android.R.attr.state_enabled}; colors[i] = getDisabledColor(ColorUtils.getAccentColor(), 0.6f); i++; states[i] = new int[]{android.R.attr.state_focused}; colors[i] = accentColor; i++; states[i] = new int[]{android.R.attr.state_activated}; colors[i] = accentColor; i++; states[i] = new int[]{android.R.attr.state_pressed}; colors[i] = accentColor; i++; states[i] = new int[]{android.R.attr.state_checked}; colors[i] = accentColor; i++; states[i] = new int[]{android.R.attr.state_selected}; colors[i] = accentColor; i++; // Default enabled state states[i] = new int[0]; colors[i] = accentColor; colorStateList = new ColorStateList(states, colors); return colorStateList; } public static ColorStateList createSwitchTrackColorStateList() { final int accentColor = ColorUtils.getAccentColor(); final int[][] states = new int[4][]; final int[] colors = new int[4]; int i = 0; // Disabled state states[i] = new int[]{-android.R.attr.state_enabled}; colors[i] = getDisabledColor(accentColor, 0.1f); i++; states[i] = new int[]{android.R.attr.state_checked}; colors[i] = getDisabledColor(accentColor, 0.3f); i++; states[i] = new int[]{-android.R.attr.state_checked}; colors[i] = getDisabledColor(Color.WHITE, 0.3f); i++; // Default enabled state states[i] = new int[0]; colors[i] = getDisabledColor(accentColor, 0.3f); return new ColorStateList(states, colors); } public static ColorStateList createSwitchThumbColorStateList() { final int accentColor = ColorUtils.getAccentColor(); final int[][] states = new int[4][]; final int[] colors = new int[4]; int i = 0; states[i] = new int[]{-android.R.attr.state_enabled}; colors[i] = getDisabledColor(accentColor, 0.6f); i++; states[i] = new int[]{-android.R.attr.state_checked}; colors[i] = Color.WHITE; i++; states[i] = new int[]{android.R.attr.state_checked}; colors[i] = accentColor; i++; // Default enabled state states[i] = new int[0]; colors[i] = accentColor; return new ColorStateList(states, colors); } static final int[] DISABLED_STATE_SET = new int[]{-16842910}; static final int[] FOCUSED_STATE_SET = new int[]{16842908}; static final int[] ACTIVATED_STATE_SET = new int[]{16843518}; static final int[] PRESSED_STATE_SET = new int[]{16842919}; static final int[] CHECKED_STATE_SET = new int[]{16842912}; static final int[] SELECTED_STATE_SET = new int[]{16842913}; static final int[] NOT_PRESSED_OR_FOCUSED_STATE_SET = new int[]{-16842919, -16842908}; static final int[] EMPTY_STATE_SET = new int[0]; public static ColorStateList createEditTextColorStateList(Context context) { final int[][] states = new int[3][]; final int[] colors = new int[3]; int i = 0; // Disabled state states[i] = DISABLED_STATE_SET; int disabledColor = getThemeAttrColor(context, android.support.v7.appcompat.R.attr.colorControlNormal); colors[i] = getDisabledColor(disabledColor, 0.6f); i++; states[i] = NOT_PRESSED_OR_FOCUSED_STATE_SET; colors[i] = getThemeAttrColor(context, android.support.v7.appcompat.R.attr.colorControlNormal); i++; // Default enabled state states[i] = EMPTY_STATE_SET; colors[i] = ColorUtils.getAccentColor(); return new ColorStateList(states, colors); } static int getDisabledColor(int color, float alpha) { final int originalAlpha = Color.alpha(color); return ColorUtils.setAlphaComponent(color, Math.round(originalAlpha * alpha)); } private static final int[] TEMP_ARRAY = new int[1]; public static int getThemeAttrColor(Context context, int attr) { TEMP_ARRAY[0] = attr; TypedArray a = context.obtainStyledAttributes(null, TEMP_ARRAY); try { return a.getColor(0, 0); } finally { a.recycle(); } } /** * Set the alpha component of {@code color} to be {@code alpha}. */ public static int setAlphaComponent(int color, int alpha) { if (alpha < 0 || alpha > 255) { throw new IllegalArgumentException("alpha must be between 0 and 255."); } return (color & 0x00ffffff) | (alpha << 24); } }