1 /* 2 * Copyright (C) 2019 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.systemui 18 19 import android.animation.ArgbEvaluator 20 import android.content.Context 21 import android.view.ContextThemeWrapper 22 import com.android.settingslib.Utils 23 import com.android.settingslib.flags.Flags.newStatusBarIcons 24 import com.android.systemui.res.R 25 26 /** 27 * A color blender for `Theme.SystemUI` and other themes. 28 * 29 * This class is used to handle colors from themes in [Context] in the following fashion: 30 * * The theme associated has a `darkIconTheme` and a `lightIconTheme` 31 * * Each of these themes define colors for the items `singleToneColor`, `backgroundColor`, 32 * and `fillColor`. 33 * 34 * In particular, `Theme.SystemUI` is a valid [Context]. If the provided [Context] does not have 35 * the correct themes, the colors that are not found will default to black. 36 * 37 * It provides a way to obtain these colors and blends for a given background intensity. 38 */ 39 class DualToneHandler(context: Context) { 40 private lateinit var darkColor: Color 41 private lateinit var lightColor: Color 42 43 init { 44 setColorsFromContext(context) 45 } 46 47 /** 48 * Sets the colors in this object from the given [Context] 49 * 50 * @param[context] A context with the appropriate themes to extract the colors from. 51 */ setColorsFromContextnull52 fun setColorsFromContext(context: Context) { 53 val dualToneDarkTheme = ContextThemeWrapper(context, 54 Utils.getThemeAttr(context, R.attr.darkIconTheme)) 55 val dualToneLightTheme = ContextThemeWrapper(context, 56 Utils.getThemeAttr(context, R.attr.lightIconTheme)) 57 if (newStatusBarIcons()) { 58 darkColor = Color( 59 android.graphics.Color.BLACK, 60 Utils.getColorAttrDefaultColor(dualToneDarkTheme, R.attr.iconBackgroundColor), 61 Utils.getColorAttrDefaultColor(dualToneDarkTheme, R.attr.fillColor)) 62 63 lightColor = Color( 64 android.graphics.Color.WHITE, 65 Utils.getColorAttrDefaultColor(dualToneLightTheme, R.attr.iconBackgroundColor), 66 Utils.getColorAttrDefaultColor(dualToneLightTheme, R.attr.fillColor)) 67 } else { 68 darkColor = Color( 69 Utils.getColorAttrDefaultColor(dualToneDarkTheme, R.attr.singleToneColor), 70 Utils.getColorAttrDefaultColor(dualToneDarkTheme, R.attr.iconBackgroundColor), 71 Utils.getColorAttrDefaultColor(dualToneDarkTheme, R.attr.fillColor)) 72 lightColor = Color( 73 Utils.getColorAttrDefaultColor(dualToneLightTheme, R.attr.singleToneColor), 74 Utils.getColorAttrDefaultColor(dualToneLightTheme, R.attr.iconBackgroundColor), 75 Utils.getColorAttrDefaultColor(dualToneLightTheme, R.attr.fillColor)) 76 } 77 } 78 getColorForDarkIntensitynull79 private fun getColorForDarkIntensity(darkIntensity: Float, lightColor: Int, darkColor: Int) = 80 ArgbEvaluator.getInstance().evaluate(darkIntensity, lightColor, darkColor) as Int 81 82 /** 83 * Blends the single color associated with the light and dark theme 84 * 85 * @param[intensity] Intensity of the background. Correspond with the "percentage" of color 86 * from `darkIconTheme` to use 87 * @return The blended color 88 */ 89 fun getSingleColor(intensity: Float) = 90 getColorForDarkIntensity(intensity, lightColor.single, darkColor.single) 91 92 /** 93 * Blends the background color associated with the light and dark theme 94 * 95 * @param[intensity] Intensity of the background. Correspond with the "percentage" of color 96 * from `darkIconTheme` to use 97 * @return The blended color 98 */ 99 fun getBackgroundColor(intensity: Float) = 100 getColorForDarkIntensity(intensity, lightColor.background, darkColor.background) 101 102 /** 103 * Blends the fill color associated with the light and dark theme 104 * 105 * @param[intensity] Intensity of the background. Correspond with the "percentage" of color 106 * from `darkIconTheme` to use 107 * @return The blended color 108 */ 109 fun getFillColor(intensity: Float) = 110 getColorForDarkIntensity(intensity, lightColor.fill, darkColor.fill) 111 112 private data class Color(val single: Int, val background: Int, val fill: Int) 113 }