1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.util; 18 19 import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_TEXT; 20 import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_THEME; 21 22 import static com.android.launcher3.LauncherPrefs.THEMED_ICONS; 23 24 import android.app.WallpaperColors; 25 import android.app.WallpaperManager; 26 import android.content.Context; 27 import android.content.res.TypedArray; 28 import android.graphics.Color; 29 import android.graphics.ColorMatrix; 30 import android.graphics.drawable.Drawable; 31 import android.util.AttributeSet; 32 import android.util.SparseArray; 33 import android.util.TypedValue; 34 35 import com.android.launcher3.LauncherPrefs; 36 import com.android.launcher3.R; 37 import com.android.launcher3.Utilities; 38 import com.android.launcher3.icons.GraphicsUtils; 39 40 /** 41 * Various utility methods associated with theming. 42 */ 43 @SuppressWarnings("NewApi") 44 public class Themes { 45 46 public static final String KEY_THEMED_ICONS = "themed_icons"; 47 getActivityThemeRes(Context context)48 public static int getActivityThemeRes(Context context) { 49 final int colorHints; 50 if (Utilities.ATLEAST_P) { 51 WallpaperColors colors = context.getSystemService(WallpaperManager.class) 52 .getWallpaperColors(WallpaperManager.FLAG_SYSTEM); 53 colorHints = colors == null ? 0 : colors.getColorHints(); 54 } else { 55 colorHints = 0; 56 } 57 return getActivityThemeRes(context, colorHints); 58 } 59 getActivityThemeRes(Context context, int wallpaperColorHints)60 public static int getActivityThemeRes(Context context, int wallpaperColorHints) { 61 boolean supportsDarkText = Utilities.ATLEAST_S 62 && (wallpaperColorHints & HINT_SUPPORTS_DARK_TEXT) != 0; 63 boolean isMainColorDark = Utilities.ATLEAST_S 64 && (wallpaperColorHints & HINT_SUPPORTS_DARK_THEME) != 0; 65 66 if (Utilities.isDarkTheme(context)) { 67 return supportsDarkText ? R.style.AppTheme_Dark_DarkText 68 : isMainColorDark ? R.style.AppTheme_Dark_DarkMainColor : R.style.AppTheme_Dark; 69 } else { 70 return supportsDarkText ? R.style.AppTheme_DarkText 71 : isMainColorDark ? R.style.AppTheme_DarkMainColor : R.style.AppTheme; 72 } 73 } 74 75 /** 76 * Returns true if workspace icon theming is enabled 77 */ isThemedIconEnabled(Context context)78 public static boolean isThemedIconEnabled(Context context) { 79 return LauncherPrefs.get(context).get(THEMED_ICONS); 80 } 81 getDefaultBodyFont(Context context)82 public static String getDefaultBodyFont(Context context) { 83 TypedArray ta = context.obtainStyledAttributes(android.R.style.TextAppearance_DeviceDefault, 84 new int[]{android.R.attr.fontFamily}); 85 String value = ta.getString(0); 86 ta.recycle(); 87 return value; 88 } 89 getDialogCornerRadius(Context context)90 public static float getDialogCornerRadius(Context context) { 91 return getDimension(context, android.R.attr.dialogCornerRadius, 92 context.getResources().getDimension(R.dimen.default_dialog_corner_radius)); 93 } 94 getDimension(Context context, int attr, float defaultValue)95 public static float getDimension(Context context, int attr, float defaultValue) { 96 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 97 float value = ta.getDimension(0, defaultValue); 98 ta.recycle(); 99 return value; 100 } 101 getColorAccent(Context context)102 public static int getColorAccent(Context context) { 103 return getAttrColor(context, android.R.attr.colorAccent); 104 } 105 106 /** Returns the background color attribute. */ getColorBackground(Context context)107 public static int getColorBackground(Context context) { 108 return getAttrColor(context, android.R.attr.colorBackground); 109 } 110 111 /** Returns the floating background color attribute. */ getColorBackgroundFloating(Context context)112 public static int getColorBackgroundFloating(Context context) { 113 return getAttrColor(context, android.R.attr.colorBackgroundFloating); 114 } 115 getAttrColor(Context context, int attr)116 public static int getAttrColor(Context context, int attr) { 117 return GraphicsUtils.getAttrColor(context, attr); 118 } 119 getAttrBoolean(Context context, int attr)120 public static boolean getAttrBoolean(Context context, int attr) { 121 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 122 boolean value = ta.getBoolean(0, false); 123 ta.recycle(); 124 return value; 125 } 126 getAttrDrawable(Context context, int attr)127 public static Drawable getAttrDrawable(Context context, int attr) { 128 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 129 Drawable value = ta.getDrawable(0); 130 ta.recycle(); 131 return value; 132 } 133 getAttrInteger(Context context, int attr)134 public static int getAttrInteger(Context context, int attr) { 135 TypedArray ta = context.obtainStyledAttributes(new int[]{attr}); 136 int value = ta.getInteger(0, 0); 137 ta.recycle(); 138 return value; 139 } 140 141 /** 142 * Scales a color matrix such that, when applied to color R G B A, it produces R' G' B' A' where 143 * R' = r * R 144 * G' = g * G 145 * B' = b * B 146 * A' = a * A 147 * 148 * The matrix will, for instance, turn white into r g b a, and black will remain black. 149 * 150 * @param color The color r g b a 151 * @param target The ColorMatrix to scale 152 */ setColorScaleOnMatrix(int color, ColorMatrix target)153 public static void setColorScaleOnMatrix(int color, ColorMatrix target) { 154 target.setScale(Color.red(color) / 255f, Color.green(color) / 255f, 155 Color.blue(color) / 255f, Color.alpha(color) / 255f); 156 } 157 158 /** 159 * Changes a color matrix such that, when applied to srcColor, it produces dstColor. 160 * 161 * Note that values on the last column of target ColorMatrix can be negative, and may result in 162 * negative values when applied on a color. Such negative values will be automatically shifted 163 * up to 0 by the framework. 164 * 165 * @param srcColor The color to start from 166 * @param dstColor The color to create by applying target on srcColor 167 * @param target The ColorMatrix to transform the color 168 */ setColorChangeOnMatrix(int srcColor, int dstColor, ColorMatrix target)169 public static void setColorChangeOnMatrix(int srcColor, int dstColor, ColorMatrix target) { 170 target.reset(); 171 target.getArray()[4] = Color.red(dstColor) - Color.red(srcColor); 172 target.getArray()[9] = Color.green(dstColor) - Color.green(srcColor); 173 target.getArray()[14] = Color.blue(dstColor) - Color.blue(srcColor); 174 target.getArray()[19] = Color.alpha(dstColor) - Color.alpha(srcColor); 175 } 176 177 /** 178 * Creates a map for attribute-name to value for all the values in {@param attrs} which can be 179 * held in memory for later use. 180 */ createValueMap(Context context, AttributeSet attrSet, IntArray keysToIgnore)181 public static SparseArray<TypedValue> createValueMap(Context context, AttributeSet attrSet, 182 IntArray keysToIgnore) { 183 int count = attrSet.getAttributeCount(); 184 IntArray attrNameArray = new IntArray(count); 185 for (int i = 0; i < count; i++) { 186 attrNameArray.add(attrSet.getAttributeNameResource(i)); 187 } 188 attrNameArray.removeAllValues(keysToIgnore); 189 190 int[] attrNames = attrNameArray.toArray(); 191 SparseArray<TypedValue> result = new SparseArray<>(attrNames.length); 192 TypedArray ta = context.obtainStyledAttributes(attrSet, attrNames); 193 for (int i = 0; i < attrNames.length; i++) { 194 TypedValue tv = new TypedValue(); 195 ta.getValue(i, tv); 196 result.put(attrNames[i], tv); 197 } 198 199 return result; 200 } 201 } 202