summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Caitlin Cassidy <ccassidy@google.com> 2022-04-22 16:41:40 +0000
committer Caitlin Cassidy <ccassidy@google.com> 2022-04-25 20:59:38 +0000
commit46956980554c91bea3cb6fa3148bb80febc2ff55 (patch)
treeb6a422e107144d157e590f80354586661c8326fd
parent6e947afdab937d2bf6d8e87bc2e52d9b9d095ba2 (diff)
[Media] Update background gradient scrim to use album theme colors.
Fixes: 220355621 Test: manual (see screenshots in bug) Change-Id: I5753a78d95e80ba65f77233f058c803aff0d4f70
-rw-r--r--packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt89
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaColorSchemes.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/ColorUtil.kt53
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/Utils.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt24
7 files changed, 153 insertions, 55 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index f925eaa0e40b..eb6705a2e979 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -15,6 +15,8 @@
*/
package com.android.keyguard;
+import static com.android.systemui.util.ColorUtilKt.getPrivateAttrColorIfUnset;
+
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
@@ -152,7 +154,7 @@ class NumPadAnimator {
ContextThemeWrapper ctw = new ContextThemeWrapper(context, mStyle);
TypedArray a = ctw.obtainStyledAttributes(customAttrs);
- mNormalColor = Utils.getPrivateAttrColorIfUnset(ctw, a, 0, 0,
+ mNormalColor = getPrivateAttrColorIfUnset(ctw, a, 0, 0,
com.android.internal.R.attr.colorSurface);
mHighlightColor = a.getColor(1, 0);
a.recycle();
diff --git a/packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt
index 5a214d1cd5e0..70052fd45abf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt
@@ -21,24 +21,41 @@ import android.animation.ValueAnimator.AnimatorUpdateListener
import android.animation.ValueAnimator
import android.content.Context
import android.content.res.ColorStateList
+import android.graphics.drawable.GradientDrawable
import com.android.internal.R
import com.android.internal.annotations.VisibleForTesting
import com.android.settingslib.Utils
import com.android.systemui.monet.ColorScheme
+import com.android.systemui.util.getColorWithAlpha
/**
- * ColorTransition is responsible for managing the animation between two specific colors.
+ * A [ColorTransition] is an object that updates the colors of views each time [updateColorScheme]
+ * is triggered.
+ */
+interface ColorTransition {
+ fun updateColorScheme(scheme: ColorScheme?)
+}
+
+/** A generic implementation of [ColorTransition] so that we can define a factory method. */
+open class GenericColorTransition(
+ private val applyTheme: (ColorScheme?) -> Unit
+) : ColorTransition {
+ override fun updateColorScheme(scheme: ColorScheme?) = applyTheme(scheme)
+}
+
+/**
+ * A [ColorTransition] that animates between two specific colors.
* It uses a ValueAnimator to execute the animation and interpolate between the source color and
* the target color.
*
* Selection of the target color from the scheme, and application of the interpolated color
* are delegated to callbacks.
*/
-open class ColorTransition(
+open class AnimatingColorTransition(
private val defaultColor: Int,
private val extractColor: (ColorScheme) -> Int,
private val applyColor: (Int) -> Unit
-) : AnimatorUpdateListener {
+) : AnimatorUpdateListener, ColorTransition {
private val argbEvaluator = ArgbEvaluator()
private val valueAnimator = buildAnimator()
@@ -53,7 +70,7 @@ open class ColorTransition(
applyColor(currentColor)
}
- fun updateColorScheme(scheme: ColorScheme?) {
+ override fun updateColorScheme(scheme: ColorScheme?) {
val newTargetColor = if (scheme == null) defaultColor else extractColor(scheme)
if (newTargetColor != targetColor) {
sourceColor = currentColor
@@ -76,7 +93,9 @@ open class ColorTransition(
}
}
-typealias ColorTransitionFactory = (Int, (ColorScheme) -> Int, (Int) -> Unit) -> ColorTransition
+typealias AnimatingColorTransitionFactory =
+ (Int, (ColorScheme) -> Int, (Int) -> Unit) -> AnimatingColorTransition
+typealias GenericColorTransitionFactory = ((ColorScheme?) -> Unit) -> GenericColorTransition
/**
* ColorSchemeTransition constructs a ColorTransition for each color in the scheme
@@ -86,27 +105,26 @@ typealias ColorTransitionFactory = (Int, (ColorScheme) -> Int, (Int) -> Unit) ->
class ColorSchemeTransition internal constructor(
private val context: Context,
mediaViewHolder: MediaViewHolder,
- colorTransitionFactory: ColorTransitionFactory
+ animatingColorTransitionFactory: AnimatingColorTransitionFactory,
+ genericColorTransitionFactory: GenericColorTransitionFactory
) {
constructor(context: Context, mediaViewHolder: MediaViewHolder) :
- this(context, mediaViewHolder, ::ColorTransition)
+ this(context, mediaViewHolder, ::AnimatingColorTransition, ::GenericColorTransition)
val bgColor = context.getColor(com.android.systemui.R.color.material_dynamic_secondary95)
- val surfaceColor = colorTransitionFactory(
+ val surfaceColor = animatingColorTransitionFactory(
bgColor,
::surfaceFromScheme
) { surfaceColor ->
val colorList = ColorStateList.valueOf(surfaceColor)
mediaViewHolder.player.backgroundTintList = colorList
- mediaViewHolder.albumView.foregroundTintList = colorList
- mediaViewHolder.albumView.backgroundTintList = colorList
mediaViewHolder.seamlessIcon.imageTintList = colorList
mediaViewHolder.seamlessText.setTextColor(surfaceColor)
mediaViewHolder.gutsViewHolder.setSurfaceColor(surfaceColor)
}
- val accentPrimary = colorTransitionFactory(
+ val accentPrimary = animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorPrimary),
::accentPrimaryFromScheme
) { accentPrimary ->
@@ -116,7 +134,7 @@ class ColorSchemeTransition internal constructor(
mediaViewHolder.gutsViewHolder.setAccentPrimaryColor(accentPrimary)
}
- val textPrimary = colorTransitionFactory(
+ val textPrimary = animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorPrimary),
::textPrimaryFromScheme
) { textPrimary ->
@@ -132,28 +150,65 @@ class ColorSchemeTransition internal constructor(
mediaViewHolder.gutsViewHolder.setTextPrimaryColor(textPrimary)
}
- val textPrimaryInverse = colorTransitionFactory(
+ val textPrimaryInverse = animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorPrimaryInverse),
::textPrimaryInverseFromScheme
) { textPrimaryInverse ->
mediaViewHolder.actionPlayPause.imageTintList = ColorStateList.valueOf(textPrimaryInverse)
}
- val textSecondary = colorTransitionFactory(
+ val textSecondary = animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorSecondary),
::textSecondaryFromScheme
) { textSecondary -> mediaViewHolder.artistText.setTextColor(textSecondary) }
- val textTertiary = colorTransitionFactory(
+ val textTertiary = animatingColorTransitionFactory(
loadDefaultColor(R.attr.textColorTertiary),
::textTertiaryFromScheme
) { textTertiary ->
mediaViewHolder.seekBar.progressBackgroundTintList = ColorStateList.valueOf(textTertiary)
}
+ // Note: This background gradient currently doesn't animate between colors.
+ val backgroundGradient = genericColorTransitionFactory { scheme ->
+ val defaultTintColor = ColorStateList.valueOf(bgColor)
+ if (scheme == null) {
+ mediaViewHolder.albumView.foregroundTintList = defaultTintColor
+ mediaViewHolder.albumView.backgroundTintList = defaultTintColor
+ return@genericColorTransitionFactory
+ }
+
+ // If there's no album art, just hide the gradient so we show the solid background.
+ val showGradient = mediaViewHolder.albumView.drawable != null
+ val startColor = getColorWithAlpha(
+ backgroundStartFromScheme(scheme),
+ alpha = if (showGradient) .25f else 0f
+ )
+ val endColor = getColorWithAlpha(
+ backgroundEndFromScheme(scheme),
+ alpha = if (showGradient) .90f else 0f
+ )
+ val gradientColors = intArrayOf(startColor, endColor)
+
+ val foregroundGradient = mediaViewHolder.albumView.foreground.mutate()
+ if (foregroundGradient is GradientDrawable) {
+ foregroundGradient.colors = gradientColors
+ }
+ val backgroundGradient = mediaViewHolder.albumView.background.mutate()
+ if (backgroundGradient is GradientDrawable) {
+ backgroundGradient.colors = gradientColors
+ }
+ }
+
val colorTransitions = arrayOf(
- surfaceColor, accentPrimary, textPrimary,
- textPrimaryInverse, textSecondary, textTertiary)
+ surfaceColor,
+ accentPrimary,
+ textPrimary,
+ textPrimaryInverse,
+ textSecondary,
+ textTertiary,
+ backgroundGradient
+ )
private fun loadDefaultColor(id: Int): Int {
return Utils.getColorAttr(context, id).defaultColor
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaColorSchemes.kt b/packages/SystemUI/src/com/android/systemui/media/MediaColorSchemes.kt
index 97c6014c91bd..5e767b0458b9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaColorSchemes.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaColorSchemes.kt
@@ -35,3 +35,9 @@ internal fun textSecondaryFromScheme(scheme: ColorScheme) = scheme.neutral2[3] /
/** Returns the tertiary text color for media controls based on the scheme. */
internal fun textTertiaryFromScheme(scheme: ColorScheme) = scheme.neutral2[5] // N2-400
+
+/** Returns the color for the start of the background gradient based on the scheme. */
+internal fun backgroundStartFromScheme(scheme: ColorScheme) = scheme.accent2[8] // A2-700
+
+/** Returns the color for the end of the background gradient based on the scheme. */
+internal fun backgroundEndFromScheme(scheme: ColorScheme) = scheme.accent1[8] // A1-700
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index 270bdc785178..0a616c095551 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -17,6 +17,7 @@ import android.util.MathUtils.lerp
import android.view.View
import com.android.systemui.animation.Interpolators
import com.android.systemui.statusbar.LightRevealEffect.Companion.getPercentPastThreshold
+import com.android.systemui.util.getColorWithAlpha
import java.util.function.Consumer
/**
@@ -367,7 +368,7 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context,
}
if (startColorAlpha > 0f) {
- canvas.drawColor(updateColorAlpha(revealGradientEndColor, startColorAlpha))
+ canvas.drawColor(getColorWithAlpha(revealGradientEndColor, startColorAlpha))
}
with(shaderGradientMatrix) {
@@ -383,15 +384,7 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context,
private fun setPaintColorFilter() {
gradientPaint.colorFilter = PorterDuffColorFilter(
- updateColorAlpha(revealGradientEndColor, revealGradientEndColorAlpha),
+ getColorWithAlpha(revealGradientEndColor, revealGradientEndColorAlpha),
PorterDuff.Mode.MULTIPLY)
}
-
- private fun updateColorAlpha(color: Int, alpha: Float): Int =
- Color.argb(
- (alpha * 255).toInt(),
- Color.red(color),
- Color.green(color),
- Color.blue(color)
- )
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/ColorUtil.kt b/packages/SystemUI/src/com/android/systemui/util/ColorUtil.kt
new file mode 100644
index 000000000000..27a53bf2ceda
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/ColorUtil.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.util
+
+import android.content.res.TypedArray
+import android.graphics.Color
+import android.view.ContextThemeWrapper
+
+/** Returns an ARGB color version of [color] at the given [alpha]. */
+fun getColorWithAlpha(color: Int, alpha: Float): Int =
+ Color.argb(
+ (alpha * 255).toInt(),
+ Color.red(color),
+ Color.green(color),
+ Color.blue(color)
+ )
+
+
+/**
+ * Returns the color provided at the specified {@param attrIndex} in {@param a} if it exists,
+ * otherwise, returns the color from the private attribute {@param privAttrId}.
+ */
+fun getPrivateAttrColorIfUnset(
+ ctw: ContextThemeWrapper, attrArray: TypedArray,
+ attrIndex: Int, defColor: Int, privAttrId: Int
+): Int {
+ // If the index is specified, use that value
+ var a = attrArray
+ if (a.hasValue(attrIndex)) {
+ return a.getColor(attrIndex, defColor)
+ }
+
+ // Otherwise fallback to the value of the private attribute
+ val customAttrs = intArrayOf(privAttrId)
+ a = ctw.obtainStyledAttributes(customAttrs)
+ val color = a.getColor(0, defColor)
+ a.recycle()
+ return color
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index 8e5e1d2e1b87..5b5dca30620a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -105,25 +105,6 @@ public class Utils {
}
/**
- * Returns the color provided at the specified {@param attrIndex} in {@param a} if it exists,
- * otherwise, returns the color from the private attribute {@param privAttrId}.
- */
- public static int getPrivateAttrColorIfUnset(ContextThemeWrapper ctw, TypedArray a,
- int attrIndex, int defColor, int privAttrId) {
- // If the index is specified, use that value
- if (a.hasValue(attrIndex)) {
- return a.getColor(attrIndex, defColor);
- }
-
- // Otherwise fallback to the value of the private attribute
- int[] customAttrs = { privAttrId };
- a = ctw.obtainStyledAttributes(customAttrs);
- int color = a.getColor(0, defColor);
- a.recycle();
- return color;
- }
-
- /**
* Gets the {@link R.dimen#status_bar_header_height_keyguard}.
*/
public static int getStatusBarHeaderHeightKeyguard(Context context) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt
index 8f967ab5294f..65d501442d87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt
@@ -19,9 +19,9 @@ package com.android.systemui.media
import org.mockito.Mockito.`when` as whenever
import android.animation.ValueAnimator
import android.graphics.Color
-import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.monet.ColorScheme
import junit.framework.Assert.assertEquals
@@ -46,28 +46,35 @@ class ColorSchemeTransitionTest : SysuiTestCase() {
private interface ExtractCB : (ColorScheme) -> Int
private interface ApplyCB : (Int) -> Unit
- private lateinit var colorTransition: ColorTransition
+ private lateinit var colorTransition: AnimatingColorTransition
private lateinit var colorSchemeTransition: ColorSchemeTransition
- @Mock private lateinit var mockTransition: ColorTransition
+ @Mock private lateinit var mockAnimatingTransition: AnimatingColorTransition
+ @Mock private lateinit var mockGenericTransition: GenericColorTransition
@Mock private lateinit var valueAnimator: ValueAnimator
@Mock private lateinit var colorScheme: ColorScheme
@Mock private lateinit var extractColor: ExtractCB
@Mock private lateinit var applyColor: ApplyCB
- private lateinit var transitionFactory: ColorTransitionFactory
+ private lateinit var animatingColorTransitionFactory: AnimatingColorTransitionFactory
+ private lateinit var genericColorTransitionFactory: GenericColorTransitionFactory
@Mock private lateinit var mediaViewHolder: MediaViewHolder
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
@Before
fun setUp() {
- transitionFactory = { default, extractColor, applyColor -> mockTransition }
+ animatingColorTransitionFactory = { _, _, _ -> mockAnimatingTransition }
+ genericColorTransitionFactory = { _ -> mockGenericTransition }
whenever(extractColor.invoke(colorScheme)).thenReturn(TARGET_COLOR)
- colorSchemeTransition = ColorSchemeTransition(context, mediaViewHolder, transitionFactory)
+ colorSchemeTransition = ColorSchemeTransition(
+ context, mediaViewHolder, animatingColorTransitionFactory, genericColorTransitionFactory
+ )
- colorTransition = object : ColorTransition(DEFAULT_COLOR, extractColor, applyColor) {
+ colorTransition = object : AnimatingColorTransition(
+ DEFAULT_COLOR, extractColor, applyColor
+ ) {
override fun buildAnimator(): ValueAnimator {
return valueAnimator
}
@@ -142,6 +149,7 @@ class ColorSchemeTransitionTest : SysuiTestCase() {
@Test
fun testColorSchemeTransition_update() {
colorSchemeTransition.updateColorScheme(colorScheme)
- verify(mockTransition, times(6)).updateColorScheme(colorScheme)
+ verify(mockAnimatingTransition, times(6)).updateColorScheme(colorScheme)
+ verify(mockGenericTransition).updateColorScheme(colorScheme)
}
}