Merge "Fix corner clipping on UMO" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c1170e1cd8
21
packages/SystemUI/res/drawable/qs_media_outline_album_bg.xml
Normal file
21
packages/SystemUI/res/drawable/qs_media_outline_album_bg.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#FFFFFFFF" />
|
||||
<corners android:radius="@dimen/notification_corner_radius"/>
|
||||
</shape>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#00000000" />
|
||||
<corners android:radius="@dimen/notification_corner_radius"/>
|
||||
</shape>
|
||||
@@ -16,7 +16,6 @@
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="@dimen/notification_corner_radius"/>
|
||||
<!-- gradient from 25% in the center to 100% at edges -->
|
||||
<gradient
|
||||
android:type="radial"
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
android:clipToPadding="true"
|
||||
android:gravity="center_horizontal|fill_vertical"
|
||||
android:forceHasOverlappingRendering="false"
|
||||
android:background="@drawable/qs_media_background"
|
||||
android:background="@drawable/qs_media_outline_layout_bg"
|
||||
android:clipToOutline="true"
|
||||
android:theme="@style/MediaPlayer">
|
||||
|
||||
<ImageView
|
||||
@@ -40,8 +41,8 @@
|
||||
android:scaleType="centerCrop"
|
||||
android:adjustViewBounds="true"
|
||||
android:clipToOutline="true"
|
||||
android:background="@drawable/qs_media_outline_album_bg"
|
||||
android:foreground="@drawable/qs_media_scrim"
|
||||
android:background="@drawable/qs_media_scrim"
|
||||
/>
|
||||
|
||||
<!-- Guideline for output switcher -->
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.animation.ValueAnimator.AnimatorUpdateListener
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.graphics.drawable.RippleDrawable
|
||||
import com.android.internal.R
|
||||
@@ -37,13 +38,6 @@ 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
|
||||
@@ -96,7 +90,6 @@ open class AnimatingColorTransition(
|
||||
|
||||
typealias AnimatingColorTransitionFactory =
|
||||
(Int, (ColorScheme) -> Int, (Int) -> Unit) -> AnimatingColorTransition
|
||||
typealias GenericColorTransitionFactory = ((ColorScheme?) -> Unit) -> GenericColorTransition
|
||||
|
||||
/**
|
||||
* ColorSchemeTransition constructs a ColorTransition for each color in the scheme
|
||||
@@ -105,23 +98,22 @@ typealias GenericColorTransitionFactory = ((ColorScheme?) -> Unit) -> GenericCol
|
||||
*/
|
||||
class ColorSchemeTransition internal constructor(
|
||||
private val context: Context,
|
||||
mediaViewHolder: MediaViewHolder,
|
||||
animatingColorTransitionFactory: AnimatingColorTransitionFactory,
|
||||
genericColorTransitionFactory: GenericColorTransitionFactory
|
||||
private val mediaViewHolder: MediaViewHolder,
|
||||
animatingColorTransitionFactory: AnimatingColorTransitionFactory
|
||||
) {
|
||||
constructor(context: Context, mediaViewHolder: MediaViewHolder) :
|
||||
this(context, mediaViewHolder, ::AnimatingColorTransition, ::GenericColorTransition)
|
||||
this(context, mediaViewHolder, ::AnimatingColorTransition)
|
||||
|
||||
private var isGradientEnabled = true
|
||||
val bgColor = context.getColor(com.android.systemui.R.color.material_dynamic_secondary95)
|
||||
|
||||
val surfaceColor = animatingColorTransitionFactory(
|
||||
bgColor,
|
||||
::surfaceFromScheme
|
||||
) { surfaceColor ->
|
||||
val colorList = ColorStateList.valueOf(surfaceColor)
|
||||
mediaViewHolder.player.backgroundTintList = colorList
|
||||
mediaViewHolder.seamlessIcon.imageTintList = colorList
|
||||
mediaViewHolder.seamlessText.setTextColor(surfaceColor)
|
||||
mediaViewHolder.albumView.backgroundTintList = colorList
|
||||
mediaViewHolder.gutsViewHolder.setSurfaceColor(surfaceColor)
|
||||
}
|
||||
|
||||
@@ -181,36 +173,15 @@ class ColorSchemeTransition internal constructor(
|
||||
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
|
||||
}
|
||||
val bgGradientStart = animatingColorTransitionFactory(
|
||||
bgColor,
|
||||
albumGradientPicker(::backgroundStartFromScheme, 0.25f)
|
||||
) { _ -> updateAlbumGradient() }
|
||||
|
||||
// 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 bgGradientEnd = animatingColorTransitionFactory(
|
||||
bgColor,
|
||||
albumGradientPicker(::backgroundEndFromScheme, 0.9f)
|
||||
) { _ -> updateAlbumGradient() }
|
||||
|
||||
val colorTransitions = arrayOf(
|
||||
surfaceColor,
|
||||
@@ -220,14 +191,37 @@ class ColorSchemeTransition internal constructor(
|
||||
textPrimaryInverse,
|
||||
textSecondary,
|
||||
textTertiary,
|
||||
backgroundGradient
|
||||
bgGradientStart,
|
||||
bgGradientEnd
|
||||
)
|
||||
|
||||
private fun updateAlbumGradient() {
|
||||
val gradient = mediaViewHolder.albumView.foreground?.mutate()
|
||||
if (gradient is GradientDrawable) {
|
||||
gradient.colors = intArrayOf(
|
||||
bgGradientStart?.currentColor ?: 0,
|
||||
bgGradientEnd?.currentColor ?: 0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun albumGradientPicker(
|
||||
inner: (ColorScheme) -> Int,
|
||||
targetAlpha: Float
|
||||
): (ColorScheme) -> Int {
|
||||
return { scheme ->
|
||||
if (isGradientEnabled)
|
||||
getColorWithAlpha(inner(scheme), targetAlpha)
|
||||
else
|
||||
Color.TRANSPARENT
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadDefaultColor(id: Int): Int {
|
||||
return Utils.getColorAttr(context, id).defaultColor
|
||||
}
|
||||
|
||||
fun updateColorScheme(colorScheme: ColorScheme?) {
|
||||
fun updateColorScheme(colorScheme: ColorScheme?, enableGradient: Boolean) {
|
||||
isGradientEnabled = enableGradient
|
||||
colorTransitions.forEach { it.updateColorScheme(colorScheme) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,6 +341,10 @@ public class MediaControlPanel {
|
||||
}
|
||||
});
|
||||
|
||||
// AlbumView uses a hardware layer so that clipping of the foreground is handled
|
||||
// with clipping the album art. Otherwise album art shows through at the edges.
|
||||
mMediaViewHolder.getAlbumView().setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
|
||||
TextView titleText = mMediaViewHolder.getTitleText();
|
||||
TextView artistText = mMediaViewHolder.getArtistText();
|
||||
AnimatorSet enter = loadAnimator(R.anim.media_metadata_enter,
|
||||
@@ -571,8 +575,8 @@ public class MediaControlPanel {
|
||||
}
|
||||
|
||||
// Capture width & height from views in foreground for artwork scaling in background
|
||||
int width = mMediaViewHolder.getPlayer().getWidth();
|
||||
int height = mMediaViewHolder.getPlayer().getHeight();
|
||||
int width = mMediaViewHolder.getAlbumView().getMeasuredWidth();
|
||||
int height = mMediaViewHolder.getAlbumView().getMeasuredHeight();
|
||||
|
||||
// WallpaperColors.fromBitmap takes a good amount of time. We do that work
|
||||
// on the background executor to avoid stalling animations on the UI Thread.
|
||||
@@ -610,7 +614,6 @@ public class MediaControlPanel {
|
||||
// Bind the album view to the artwork or a transition drawable
|
||||
ImageView albumView = mMediaViewHolder.getAlbumView();
|
||||
albumView.setPadding(0, 0, 0, 0);
|
||||
albumView.setClipToOutline(true);
|
||||
if (updateBackground || (!mIsArtworkBound && isArtworkBound)) {
|
||||
if (mPrevArtwork == null) {
|
||||
albumView.setImageDrawable(artwork);
|
||||
@@ -634,7 +637,7 @@ public class MediaControlPanel {
|
||||
}
|
||||
|
||||
// Transition Colors to current color scheme
|
||||
mColorSchemeTransition.updateColorScheme(colorScheme);
|
||||
mColorSchemeTransition.updateColorScheme(colorScheme, mIsArtworkBound);
|
||||
|
||||
// App icon - use notification icon
|
||||
ImageView appIconView = mMediaViewHolder.getAppIcon();
|
||||
@@ -925,7 +928,7 @@ public class MediaControlPanel {
|
||||
InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_MEDIA_PLAYER) {
|
||||
@Override
|
||||
protected float getCurrentTopCornerRadius() {
|
||||
return ((IlluminationDrawable) player.getBackground()).getCornerRadius();
|
||||
return mContext.getResources().getDimension(R.dimen.notification_corner_radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -933,20 +936,6 @@ public class MediaControlPanel {
|
||||
// TODO(b/184121838): Make IlluminationDrawable support top and bottom radius.
|
||||
return getCurrentTopCornerRadius();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setBackgroundCornerRadius(Drawable background, float topCornerRadius,
|
||||
float bottomCornerRadius) {
|
||||
// TODO(b/184121838): Make IlluminationDrawable support top and bottom radius.
|
||||
float radius = Math.min(topCornerRadius, bottomCornerRadius);
|
||||
((IlluminationDrawable) background).setCornerRadiusOverride(radius);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) {
|
||||
super.onLaunchAnimationEnd(isExpandingFullyAbove);
|
||||
((IlluminationDrawable) player.getBackground()).setCornerRadiusOverride(null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -69,23 +69,6 @@ class MediaViewHolder constructor(itemView: View) {
|
||||
|
||||
val actionsTopBarrier = itemView.requireViewById<Barrier>(R.id.media_action_barrier_top)
|
||||
|
||||
init {
|
||||
(player.background as IlluminationDrawable).let {
|
||||
it.registerLightSource(seamless)
|
||||
it.registerLightSource(gutsViewHolder.cancel)
|
||||
it.registerLightSource(gutsViewHolder.dismiss)
|
||||
it.registerLightSource(gutsViewHolder.settings)
|
||||
it.registerLightSource(actionPlayPause)
|
||||
it.registerLightSource(actionNext)
|
||||
it.registerLightSource(actionPrev)
|
||||
it.registerLightSource(action0)
|
||||
it.registerLightSource(action1)
|
||||
it.registerLightSource(action2)
|
||||
it.registerLightSource(action3)
|
||||
it.registerLightSource(action4)
|
||||
}
|
||||
}
|
||||
|
||||
fun getAction(id: Int): ImageButton {
|
||||
return when (id) {
|
||||
R.id.actionPlayPause -> actionPlayPause
|
||||
@@ -161,7 +144,6 @@ class MediaViewHolder constructor(itemView: View) {
|
||||
R.id.media_scrubbing_total_time
|
||||
)
|
||||
|
||||
|
||||
// Buttons used for notification-based actions
|
||||
val genericButtonIds = setOf(
|
||||
R.id.action0,
|
||||
|
||||
@@ -50,14 +50,12 @@ class ColorSchemeTransitionTest : SysuiTestCase() {
|
||||
private lateinit var colorSchemeTransition: ColorSchemeTransition
|
||||
|
||||
@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 animatingColorTransitionFactory: AnimatingColorTransitionFactory
|
||||
private lateinit var genericColorTransitionFactory: GenericColorTransitionFactory
|
||||
@Mock private lateinit var mediaViewHolder: MediaViewHolder
|
||||
|
||||
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
|
||||
@@ -65,11 +63,10 @@ class ColorSchemeTransitionTest : SysuiTestCase() {
|
||||
@Before
|
||||
fun setUp() {
|
||||
animatingColorTransitionFactory = { _, _, _ -> mockAnimatingTransition }
|
||||
genericColorTransitionFactory = { _ -> mockGenericTransition }
|
||||
whenever(extractColor.invoke(colorScheme)).thenReturn(TARGET_COLOR)
|
||||
|
||||
colorSchemeTransition = ColorSchemeTransition(
|
||||
context, mediaViewHolder, animatingColorTransitionFactory, genericColorTransitionFactory
|
||||
context, mediaViewHolder, animatingColorTransitionFactory
|
||||
)
|
||||
|
||||
colorTransition = object : AnimatingColorTransition(
|
||||
@@ -148,8 +145,7 @@ class ColorSchemeTransitionTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun testColorSchemeTransition_update() {
|
||||
colorSchemeTransition.updateColorScheme(colorScheme)
|
||||
verify(mockAnimatingTransition, times(7)).updateColorScheme(colorScheme)
|
||||
verify(mockGenericTransition).updateColorScheme(colorScheme)
|
||||
colorSchemeTransition.updateColorScheme(colorScheme, true)
|
||||
verify(mockAnimatingTransition, times(9)).updateColorScheme(colorScheme)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,6 +536,13 @@ public class MediaControlPanelTest : SysuiTestCase() {
|
||||
verify(expandedSet).setVisibility(R.id.actionNext, ConstraintSet.INVISIBLE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bindAlbumView_testHardwareAfterAttach() {
|
||||
player.attachPlayer(viewHolder)
|
||||
|
||||
verify(albumView).setLayerType(View.LAYER_TYPE_HARDWARE, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bindAlbumView_setAfterExecutors() {
|
||||
val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
|
||||
|
||||
Reference in New Issue
Block a user