1616
1717package com.android.systemui.volume.dialog.captions.ui.binder
1818
19+ import android.content.Context
20+ import android.database.ContentObserver
21+ import android.graphics.drawable.Drawable
22+ import android.graphics.drawable.GradientDrawable
23+ import android.graphics.drawable.InsetDrawable
1924import android.graphics.drawable.TransitionDrawable
2025import android.os.Handler
26+ import android.os.UserHandle
27+ import android.provider.Settings
2128import android.view.View
2229import com.android.app.tracing.coroutines.launchInTraced
2330import com.android.app.tracing.coroutines.launchTraced
31+ import com.android.internal.R as internalR
2432import com.android.systemui.Flags
2533import com.android.systemui.dagger.qualifiers.Background
2634import com.android.systemui.res.R
@@ -34,6 +42,7 @@ import javax.inject.Inject
3442import kotlinx.coroutines.CoroutineScope
3543import kotlinx.coroutines.flow.onEach
3644import kotlinx.coroutines.flow.withIndex
45+ import kotlinx.coroutines.job
3746
3847/* * Binds the captions button view. */
3948@VolumeDialogScope
@@ -55,6 +64,39 @@ constructor(
5564 dialogViewModel.addTouchableBounds(captionsButton)
5665 }
5766
67+ val contentResolver = captionsButton.context.contentResolver
68+ var gradientEnabled = isVolumeGradientEnabled(captionsButton.context)
69+ var gradientColorsForRinger = getGradientColorsForRinger(captionsButton.context)
70+
71+ val gradientObserver =
72+ object : ContentObserver (null ) {
73+ override fun onChange (selfChange : Boolean ) {
74+ gradientEnabled = isVolumeGradientEnabled(view.context)
75+ gradientColorsForRinger = getGradientColorsForRinger(view.context)
76+ }
77+ }
78+
79+ contentResolver.registerContentObserver(
80+ Settings .System .getUriFor(Settings .System .VOLUME_SLIDER_GRADIENT ),
81+ false , gradientObserver, UserHandle .USER_ALL ,
82+ )
83+ contentResolver.registerContentObserver(
84+ Settings .System .getUriFor(Settings .System .CUSTOM_GRADIENT_COLOR_MODE ),
85+ false , gradientObserver, UserHandle .USER_ALL ,
86+ )
87+ contentResolver.registerContentObserver(
88+ Settings .System .getUriFor(Settings .System .CUSTOM_GRADIENT_START_COLOR ),
89+ false , gradientObserver, UserHandle .USER_ALL ,
90+ )
91+ contentResolver.registerContentObserver(
92+ Settings .System .getUriFor(Settings .System .CUSTOM_GRADIENT_END_COLOR ),
93+ false , gradientObserver, UserHandle .USER_ALL ,
94+ )
95+
96+ coroutineContext.job.invokeOnCompletion {
97+ contentResolver.unregisterContentObserver(gradientObserver)
98+ }
99+
58100 viewModel.isVisible
59101 .onEach { isVisible ->
60102 captionsButton.visibility =
@@ -88,6 +130,10 @@ constructor(
88130 )
89131 )
90132
133+ if (isEnabled && gradientEnabled) {
134+ applyGradientSelectionBackground(this , gradientColorsForRinger)
135+ }
136+
91137 val transition = background as TransitionDrawable
92138 transition.isCrossFadeEnabled = true
93139 if (index == 0 ) {
@@ -116,7 +162,70 @@ constructor(
116162 )
117163 }
118164
165+ private fun isVolumeGradientEnabled (context : Context ): Boolean {
166+ return Settings .System .getIntForUser(
167+ context.contentResolver, Settings .System .VOLUME_SLIDER_GRADIENT , 0 ,
168+ UserHandle .USER_CURRENT ) != 0
169+ }
170+
171+ private fun getGradientColorsForRinger (context : Context ): Pair <Int , Int > {
172+ val resolver = context.contentResolver
173+
174+ val mode = Settings .System .getIntForUser(
175+ resolver, Settings .System .CUSTOM_GRADIENT_COLOR_MODE , 0 ,
176+ UserHandle .USER_CURRENT ,
177+ )
178+
179+ val primary = context.getColor(internalR.color.materialColorPrimary)
180+ val secondary = context.getColor(internalR.color.materialColorSecondary)
181+
182+ if (mode == 1 ) {
183+ val start = Settings .System .getIntForUser(
184+ resolver, Settings .System .CUSTOM_GRADIENT_START_COLOR , 0 ,
185+ UserHandle .USER_CURRENT ,
186+ )
187+ val end = Settings .System .getIntForUser(
188+ resolver, Settings .System .CUSTOM_GRADIENT_END_COLOR , 0 ,
189+ UserHandle .USER_CURRENT ,
190+ )
191+
192+ val startColor = if (start != 0 ) start else primary
193+ val endColor = if (end != 0 ) end else secondary
194+
195+ return startColor to endColor
196+ }
197+
198+ return primary to secondary
199+ }
200+
201+ private fun applyGradientSelectionBackground (
202+ button : CaptionsToggleImageButton ,
203+ gradientColorsForRinger : Pair <Int , Int >,
204+ ) {
205+ val (startColor, endColor) = gradientColorsForRinger
206+ val shape = button.backgroundShape()
207+ shape.orientation = GradientDrawable .Orientation .TOP_BOTTOM
208+ shape.colors = intArrayOf(startColor, endColor)
209+ button.background.invalidateSelf()
210+ }
211+
119212 private companion object {
120213 const val DURATION_MILLIS = 500
121214 }
122215}
216+
217+ private fun CaptionsToggleImageButton.backgroundShape (): GradientDrawable {
218+ val td = background as TransitionDrawable
219+
220+ fun unwrap (d : Drawable ): GradientDrawable ? {
221+ return when (d) {
222+ is GradientDrawable -> d
223+ is InsetDrawable -> d.drawable as ? GradientDrawable
224+ else -> null
225+ }
226+ }
227+
228+ return unwrap(td.getDrawable(1 ))
229+ ? : unwrap(td.getDrawable(0 ))
230+ ? : throw IllegalStateException (" Captions button background is not a GradientDrawable" )
231+ }
0 commit comments