Loading packages/SystemUI/res/color/qs_tile_ripple_color.xml 0 → 100644 +25 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- ~ Copyright (C) 2023 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. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="?android:attr/colorControlHighlight" android:state_hovered="true" android:state_pressed="true" /> <!-- RippleDrawable has default way of handling hover state with highlighting but it's not consistent with our approach so we make highlighting invisible and instead do custom handling of hover state on a different level --> <item android:color="@color/transparent" android:state_hovered="true" /> <item android:color="?android:attr/colorControlHighlight" /> </selector> No newline at end of file packages/SystemUI/res/drawable/qs_tile_background.xml +20 −4 Original line number Diff line number Diff line Loading @@ -15,9 +15,25 @@ ~ limitations under the License. --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:attr/colorControlHighlight"> android:color="@color/qs_tile_ripple_color"> <item android:id="@android:id/mask" android:drawable="@drawable/qs_tile_background_shape" /> <item android:id="@id/background"> <layer-list> <item android:id="@+id/qs_tile_background_base" android:drawable="@drawable/qs_tile_background_shape" /> <item android:id="@id/background" <item android:id="@+id/qs_tile_background_overlay"> <selector> <item android:state_hovered="true" android:drawable="@drawable/qs_tile_background_shape" /> <item android:state_focused="true" android:drawable="@drawable/qs_tile_background_shape" /> </selector> </item> </layer-list> </item> </ripple> No newline at end of file packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +56 −13 Original line number Diff line number Diff line Loading @@ -23,7 +23,10 @@ import android.content.Context import android.content.res.ColorStateList import android.content.res.Configuration import android.content.res.Resources.ID_NULL import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.graphics.drawable.RippleDrawable import android.os.Trace import android.service.quicksettings.Tile Loading @@ -44,7 +47,6 @@ import android.widget.TextView import androidx.annotation.VisibleForTesting import com.android.settingslib.Utils import com.android.systemui.FontSizeUtils import com.android.systemui.res.R import com.android.systemui.animation.LaunchableView import com.android.systemui.animation.LaunchableViewDelegate import com.android.systemui.plugins.qs.QSIconView Loading @@ -53,6 +55,7 @@ import com.android.systemui.plugins.qs.QSTile.BooleanState import com.android.systemui.plugins.qs.QSTileView import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSIconViewImpl.QS_ANIM_LENGTH import com.android.systemui.res.R import java.util.Objects private const val TAG = "QSTileViewImpl" Loading @@ -67,6 +70,7 @@ open class QSTileViewImpl @JvmOverloads constructor( private const val LABEL_NAME = "label" private const val SECONDARY_LABEL_NAME = "secondaryLabel" private const val CHEVRON_NAME = "chevron" private const val OVERLAY_NAME = "overlay" const val UNAVAILABLE_ALPHA = 0.3f @VisibleForTesting internal const val TILE_STATE_RES_PREFIX = "tile_states_" Loading Loading @@ -97,6 +101,13 @@ open class QSTileViewImpl @JvmOverloads constructor( private val colorInactive = Utils.getColorAttrDefaultColor(context, R.attr.shadeInactive) private val colorUnavailable = Utils.getColorAttrDefaultColor(context, R.attr.shadeDisabled) private val overlayColorActive = Utils.applyAlpha( /* alpha= */ 0.11f, Utils.getColorAttrDefaultColor(context, R.attr.onShadeActive)) private val overlayColorInactive = Utils.applyAlpha( /* alpha= */ 0.08f, Utils.getColorAttrDefaultColor(context, R.attr.onShadeInactive)) private val colorLabelActive = Utils.getColorAttrDefaultColor(context, R.attr.onShadeActive) private val colorLabelInactive = Utils.getColorAttrDefaultColor(context, R.attr.onShadeInactive) private val colorLabelUnavailable = Loading @@ -123,8 +134,13 @@ open class QSTileViewImpl @JvmOverloads constructor( protected var showRippleEffect = true private lateinit var ripple: RippleDrawable private lateinit var colorBackgroundDrawable: Drawable private var paintColor: Int = 0 private lateinit var backgroundDrawable: LayerDrawable private lateinit var backgroundBaseDrawable: Drawable private lateinit var backgroundOverlayDrawable: Drawable private var backgroundColor: Int = 0 private var backgroundOverlayColor: Int = 0 private val singleAnimator: ValueAnimator = ValueAnimator().apply { setDuration(QS_ANIM_LENGTH) addUpdateListener { animation -> Loading @@ -134,7 +150,8 @@ open class QSTileViewImpl @JvmOverloads constructor( animation.getAnimatedValue(BACKGROUND_NAME) as Int, animation.getAnimatedValue(LABEL_NAME) as Int, animation.getAnimatedValue(SECONDARY_LABEL_NAME) as Int, animation.getAnimatedValue(CHEVRON_NAME) as Int animation.getAnimatedValue(CHEVRON_NAME) as Int, animation.getAnimatedValue(OVERLAY_NAME) as Int, ) } } Loading Loading @@ -263,7 +280,12 @@ open class QSTileViewImpl @JvmOverloads constructor( fun createTileBackground(): Drawable { ripple = mContext.getDrawable(R.drawable.qs_tile_background) as RippleDrawable colorBackgroundDrawable = ripple.findDrawableByLayerId(R.id.background) backgroundDrawable = ripple.findDrawableByLayerId(R.id.background) as LayerDrawable backgroundBaseDrawable = backgroundDrawable.findDrawableByLayerId(R.id.qs_tile_background_base) backgroundOverlayDrawable = backgroundDrawable.findDrawableByLayerId(R.id.qs_tile_background_overlay) backgroundOverlayDrawable.mutate().setTintMode(PorterDuff.Mode.SRC) return ripple } Loading Loading @@ -343,10 +365,10 @@ open class QSTileViewImpl @JvmOverloads constructor( ripple.also { // In case that the colorBackgroundDrawable was used as the background, make sure // it has the correct callback instead of null colorBackgroundDrawable.callback = it backgroundDrawable.callback = it } } else { colorBackgroundDrawable backgroundDrawable } } Loading Loading @@ -512,7 +534,7 @@ open class QSTileViewImpl @JvmOverloads constructor( singleAnimator.setValues( colorValuesHolder( BACKGROUND_NAME, paintColor, backgroundColor, getBackgroundColorForState(state.state, state.disabledByPolicy) ), colorValuesHolder( Loading @@ -529,6 +551,11 @@ open class QSTileViewImpl @JvmOverloads constructor( CHEVRON_NAME, chevronView.imageTintList?.defaultColor ?: 0, getChevronColorForState(state.state, state.disabledByPolicy) ), colorValuesHolder( OVERLAY_NAME, backgroundOverlayColor, getOverlayColorForState(state.state) ) ) singleAnimator.start() Loading @@ -537,7 +564,8 @@ open class QSTileViewImpl @JvmOverloads constructor( getBackgroundColorForState(state.state, state.disabledByPolicy), getLabelColorForState(state.state, state.disabledByPolicy), getSecondaryLabelColorForState(state.state, state.disabledByPolicy), getChevronColorForState(state.state, state.disabledByPolicy) getChevronColorForState(state.state, state.disabledByPolicy), getOverlayColorForState(state.state) ) } } Loading @@ -555,17 +583,19 @@ open class QSTileViewImpl @JvmOverloads constructor( backgroundColor: Int, labelColor: Int, secondaryLabelColor: Int, chevronColor: Int chevronColor: Int, overlayColor: Int, ) { setColor(backgroundColor) setLabelColor(labelColor) setSecondaryLabelColor(secondaryLabelColor) setChevronColor(chevronColor) setOverlayColor(overlayColor) } private fun setColor(color: Int) { colorBackgroundDrawable.mutate().setTint(color) paintColor = color backgroundBaseDrawable.mutate().setTint(color) backgroundColor = color } private fun setLabelColor(color: Int) { Loading @@ -580,6 +610,11 @@ open class QSTileViewImpl @JvmOverloads constructor( chevronView.imageTintList = ColorStateList.valueOf(color) } private fun setOverlayColor(overlayColor: Int) { backgroundOverlayDrawable.setTint(overlayColor) backgroundOverlayColor = overlayColor } private fun loadSideViewDrawableIfNecessary(state: QSTile.State) { if (state.sideViewCustomDrawable != null) { customDrawableView.setImageDrawable(state.sideViewCustomDrawable) Loading Loading @@ -654,9 +689,17 @@ open class QSTileViewImpl @JvmOverloads constructor( private fun getChevronColorForState(state: Int, disabledByPolicy: Boolean = false): Int = getSecondaryLabelColorForState(state, disabledByPolicy) private fun getOverlayColorForState(state: Int): Int { return when (state) { Tile.STATE_ACTIVE -> overlayColorActive Tile.STATE_INACTIVE -> overlayColorInactive else -> Color.TRANSPARENT } } @VisibleForTesting internal fun getCurrentColors(): List<Int> = listOf( paintColor, backgroundColor, label.currentTextColor, secondaryLabel.currentTextColor, chevronView.imageTintList?.defaultColor ?: 0 Loading Loading
packages/SystemUI/res/color/qs_tile_ripple_color.xml 0 → 100644 +25 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- ~ Copyright (C) 2023 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. --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="?android:attr/colorControlHighlight" android:state_hovered="true" android:state_pressed="true" /> <!-- RippleDrawable has default way of handling hover state with highlighting but it's not consistent with our approach so we make highlighting invisible and instead do custom handling of hover state on a different level --> <item android:color="@color/transparent" android:state_hovered="true" /> <item android:color="?android:attr/colorControlHighlight" /> </selector> No newline at end of file
packages/SystemUI/res/drawable/qs_tile_background.xml +20 −4 Original line number Diff line number Diff line Loading @@ -15,9 +15,25 @@ ~ limitations under the License. --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?android:attr/colorControlHighlight"> android:color="@color/qs_tile_ripple_color"> <item android:id="@android:id/mask" android:drawable="@drawable/qs_tile_background_shape" /> <item android:id="@id/background"> <layer-list> <item android:id="@+id/qs_tile_background_base" android:drawable="@drawable/qs_tile_background_shape" /> <item android:id="@id/background" <item android:id="@+id/qs_tile_background_overlay"> <selector> <item android:state_hovered="true" android:drawable="@drawable/qs_tile_background_shape" /> <item android:state_focused="true" android:drawable="@drawable/qs_tile_background_shape" /> </selector> </item> </layer-list> </item> </ripple> No newline at end of file
packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +56 −13 Original line number Diff line number Diff line Loading @@ -23,7 +23,10 @@ import android.content.Context import android.content.res.ColorStateList import android.content.res.Configuration import android.content.res.Resources.ID_NULL import android.graphics.Color import android.graphics.PorterDuff import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.graphics.drawable.RippleDrawable import android.os.Trace import android.service.quicksettings.Tile Loading @@ -44,7 +47,6 @@ import android.widget.TextView import androidx.annotation.VisibleForTesting import com.android.settingslib.Utils import com.android.systemui.FontSizeUtils import com.android.systemui.res.R import com.android.systemui.animation.LaunchableView import com.android.systemui.animation.LaunchableViewDelegate import com.android.systemui.plugins.qs.QSIconView Loading @@ -53,6 +55,7 @@ import com.android.systemui.plugins.qs.QSTile.BooleanState import com.android.systemui.plugins.qs.QSTileView import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSIconViewImpl.QS_ANIM_LENGTH import com.android.systemui.res.R import java.util.Objects private const val TAG = "QSTileViewImpl" Loading @@ -67,6 +70,7 @@ open class QSTileViewImpl @JvmOverloads constructor( private const val LABEL_NAME = "label" private const val SECONDARY_LABEL_NAME = "secondaryLabel" private const val CHEVRON_NAME = "chevron" private const val OVERLAY_NAME = "overlay" const val UNAVAILABLE_ALPHA = 0.3f @VisibleForTesting internal const val TILE_STATE_RES_PREFIX = "tile_states_" Loading Loading @@ -97,6 +101,13 @@ open class QSTileViewImpl @JvmOverloads constructor( private val colorInactive = Utils.getColorAttrDefaultColor(context, R.attr.shadeInactive) private val colorUnavailable = Utils.getColorAttrDefaultColor(context, R.attr.shadeDisabled) private val overlayColorActive = Utils.applyAlpha( /* alpha= */ 0.11f, Utils.getColorAttrDefaultColor(context, R.attr.onShadeActive)) private val overlayColorInactive = Utils.applyAlpha( /* alpha= */ 0.08f, Utils.getColorAttrDefaultColor(context, R.attr.onShadeInactive)) private val colorLabelActive = Utils.getColorAttrDefaultColor(context, R.attr.onShadeActive) private val colorLabelInactive = Utils.getColorAttrDefaultColor(context, R.attr.onShadeInactive) private val colorLabelUnavailable = Loading @@ -123,8 +134,13 @@ open class QSTileViewImpl @JvmOverloads constructor( protected var showRippleEffect = true private lateinit var ripple: RippleDrawable private lateinit var colorBackgroundDrawable: Drawable private var paintColor: Int = 0 private lateinit var backgroundDrawable: LayerDrawable private lateinit var backgroundBaseDrawable: Drawable private lateinit var backgroundOverlayDrawable: Drawable private var backgroundColor: Int = 0 private var backgroundOverlayColor: Int = 0 private val singleAnimator: ValueAnimator = ValueAnimator().apply { setDuration(QS_ANIM_LENGTH) addUpdateListener { animation -> Loading @@ -134,7 +150,8 @@ open class QSTileViewImpl @JvmOverloads constructor( animation.getAnimatedValue(BACKGROUND_NAME) as Int, animation.getAnimatedValue(LABEL_NAME) as Int, animation.getAnimatedValue(SECONDARY_LABEL_NAME) as Int, animation.getAnimatedValue(CHEVRON_NAME) as Int animation.getAnimatedValue(CHEVRON_NAME) as Int, animation.getAnimatedValue(OVERLAY_NAME) as Int, ) } } Loading Loading @@ -263,7 +280,12 @@ open class QSTileViewImpl @JvmOverloads constructor( fun createTileBackground(): Drawable { ripple = mContext.getDrawable(R.drawable.qs_tile_background) as RippleDrawable colorBackgroundDrawable = ripple.findDrawableByLayerId(R.id.background) backgroundDrawable = ripple.findDrawableByLayerId(R.id.background) as LayerDrawable backgroundBaseDrawable = backgroundDrawable.findDrawableByLayerId(R.id.qs_tile_background_base) backgroundOverlayDrawable = backgroundDrawable.findDrawableByLayerId(R.id.qs_tile_background_overlay) backgroundOverlayDrawable.mutate().setTintMode(PorterDuff.Mode.SRC) return ripple } Loading Loading @@ -343,10 +365,10 @@ open class QSTileViewImpl @JvmOverloads constructor( ripple.also { // In case that the colorBackgroundDrawable was used as the background, make sure // it has the correct callback instead of null colorBackgroundDrawable.callback = it backgroundDrawable.callback = it } } else { colorBackgroundDrawable backgroundDrawable } } Loading Loading @@ -512,7 +534,7 @@ open class QSTileViewImpl @JvmOverloads constructor( singleAnimator.setValues( colorValuesHolder( BACKGROUND_NAME, paintColor, backgroundColor, getBackgroundColorForState(state.state, state.disabledByPolicy) ), colorValuesHolder( Loading @@ -529,6 +551,11 @@ open class QSTileViewImpl @JvmOverloads constructor( CHEVRON_NAME, chevronView.imageTintList?.defaultColor ?: 0, getChevronColorForState(state.state, state.disabledByPolicy) ), colorValuesHolder( OVERLAY_NAME, backgroundOverlayColor, getOverlayColorForState(state.state) ) ) singleAnimator.start() Loading @@ -537,7 +564,8 @@ open class QSTileViewImpl @JvmOverloads constructor( getBackgroundColorForState(state.state, state.disabledByPolicy), getLabelColorForState(state.state, state.disabledByPolicy), getSecondaryLabelColorForState(state.state, state.disabledByPolicy), getChevronColorForState(state.state, state.disabledByPolicy) getChevronColorForState(state.state, state.disabledByPolicy), getOverlayColorForState(state.state) ) } } Loading @@ -555,17 +583,19 @@ open class QSTileViewImpl @JvmOverloads constructor( backgroundColor: Int, labelColor: Int, secondaryLabelColor: Int, chevronColor: Int chevronColor: Int, overlayColor: Int, ) { setColor(backgroundColor) setLabelColor(labelColor) setSecondaryLabelColor(secondaryLabelColor) setChevronColor(chevronColor) setOverlayColor(overlayColor) } private fun setColor(color: Int) { colorBackgroundDrawable.mutate().setTint(color) paintColor = color backgroundBaseDrawable.mutate().setTint(color) backgroundColor = color } private fun setLabelColor(color: Int) { Loading @@ -580,6 +610,11 @@ open class QSTileViewImpl @JvmOverloads constructor( chevronView.imageTintList = ColorStateList.valueOf(color) } private fun setOverlayColor(overlayColor: Int) { backgroundOverlayDrawable.setTint(overlayColor) backgroundOverlayColor = overlayColor } private fun loadSideViewDrawableIfNecessary(state: QSTile.State) { if (state.sideViewCustomDrawable != null) { customDrawableView.setImageDrawable(state.sideViewCustomDrawable) Loading Loading @@ -654,9 +689,17 @@ open class QSTileViewImpl @JvmOverloads constructor( private fun getChevronColorForState(state: Int, disabledByPolicy: Boolean = false): Int = getSecondaryLabelColorForState(state, disabledByPolicy) private fun getOverlayColorForState(state: Int): Int { return when (state) { Tile.STATE_ACTIVE -> overlayColorActive Tile.STATE_INACTIVE -> overlayColorInactive else -> Color.TRANSPARENT } } @VisibleForTesting internal fun getCurrentColors(): List<Int> = listOf( paintColor, backgroundColor, label.currentTextColor, secondaryLabel.currentTextColor, chevronView.imageTintList?.defaultColor ?: 0 Loading