Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2b1f0e0 authored by Michael Mikhail's avatar Michael Mikhail
Browse files

Use runnable for drawer update instead of endListener

Flag: com.android.systemui.volume_redesign
Bug: 369995871
Test: Checked UI.
Change-Id: I91c73967c532185449df29e324dd3f29f42e50dc
parent d53aae77
Loading
Loading
Loading
Loading
+33 −41
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.widget.ImageButton
import androidx.annotation.LayoutRes
import androidx.compose.ui.util.fastForEachIndexed
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FloatValueHolder
import androidx.dynamicanimation.animation.SpringAnimation
import androidx.dynamicanimation.animation.SpringForce
@@ -44,13 +43,16 @@ import com.android.systemui.volume.dialog.ui.utils.suspendAnimate
import javax.inject.Inject
import kotlin.properties.Delegates
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.launch

private const val CLOSE_DRAWER_DELAY = 300L

@OptIn(ExperimentalCoroutinesApi::class)
@VolumeDialogScope
class VolumeDialogRingerViewBinder
@Inject
@@ -95,7 +97,7 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
        volumeDialogBackgroundView.background = volumeDialogBackgroundView.background.mutate()

        viewModel.ringerViewModel
            .onEach { ringerState ->
            .mapLatest { ringerState ->
                when (ringerState) {
                    is RingerViewModelState.Available -> {
                        val uiModel = ringerState.uiModel
@@ -221,15 +223,6 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
            val unselectedButton =
                getChildAt(count - previousIndex - 1)
                    .requireViewById<ImageButton>(R.id.volume_drawer_button)

            // On roundness animation end.
            val roundnessAnimationEndListener =
                DynamicAnimation.OnAnimationEndListener { _, _, _, _ ->
                    postDelayed(
                        { bindButtons(viewModel, uiModel, onAnimationEnd, isAnimated = true) },
                        CLOSE_DRAWER_DELAY,
                    )
                }
            // We only need to execute on roundness animation end and volume dialog background
            // progress update once because these changes should be applied once on volume dialog
            // background and ringer drawer views.
@@ -242,7 +235,6 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
                    } else {
                        { _, _ -> }
                    },
                    roundnessAnimationEndListener,
                )
            }
            val unselectedCornerRadius =
@@ -257,6 +249,12 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
                    },
                )
            }
            coroutineScope {
                launch {
                    delay(CLOSE_DRAWER_DELAY)
                    bindButtons(viewModel, uiModel, onAnimationEnd, isAnimated = true)
                }
            }
        } else {
            bindButtons(viewModel, uiModel, onAnimationEnd)
        }
@@ -348,7 +346,6 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
    private suspend fun ImageButton.animateTo(
        ringerButtonUiModel: RingerButtonUiModel,
        onProgressChanged: (Float, Boolean) -> Unit = { _, _ -> },
        roundnessAnimationEndListener: DynamicAnimation.OnAnimationEndListener? = null,
    ) {
        val roundnessAnimation =
            SpringAnimation(FloatValueHolder(0F)).setSpring(roundnessSpringForce)
@@ -356,14 +353,9 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
        val radius = (background as GradientDrawable).cornerRadius
        val cornerRadiusDiff =
            ringerButtonUiModel.cornerRadius - (background as GradientDrawable).cornerRadius
        val roundnessAnimationUpdateListener =
            DynamicAnimation.OnAnimationUpdateListener { _, value, _ ->
                onProgressChanged(value, cornerRadiusDiff > 0F)
                (background as GradientDrawable).cornerRadius = radius + value * cornerRadiusDiff
                background.invalidateSelf()
            }
        val colorAnimationUpdateListener =
            DynamicAnimation.OnAnimationUpdateListener { _, value, _ ->
        coroutineScope {
            launch {
                colorAnimation.suspendAnimate { value ->
                    val currentIconColor =
                        rgbEvaluator.evaluate(
                            value.coerceIn(0F, 1F),
@@ -381,12 +373,12 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) {
                    background.invalidateSelf()
                    setColorFilter(currentIconColor)
                }
        coroutineScope {
            launch { colorAnimation.suspendAnimate(colorAnimationUpdateListener) }
            roundnessAnimation.suspendAnimate(
                roundnessAnimationUpdateListener,
                roundnessAnimationEndListener,
            )
            }
            roundnessAnimation.suspendAnimate { value ->
                onProgressChanged(value, cornerRadiusDiff > 0F)
                (background as GradientDrawable).cornerRadius = radius + value * cornerRadiusDiff
                background.invalidateSelf()
            }
        }
    }

+14 −15
Original line number Diff line number Diff line
@@ -87,19 +87,18 @@ suspend fun <T> ValueAnimator.suspendAnimate(onValueChanged: (T) -> Unit) {
 * Starts spring animation and suspends until it's finished. Cancels the animation if the running
 * coroutine is cancelled.
 */
suspend fun SpringAnimation.suspendAnimate(
    animationUpdateListener: DynamicAnimation.OnAnimationUpdateListener? = null,
    animationEndListener: DynamicAnimation.OnAnimationEndListener? = null,
) = suspendCancellableCoroutine { continuation ->
    animationUpdateListener?.let(::addUpdateListener)
    addEndListener { animation, canceled, value, velocity ->
        continuation.resumeIfCan(Unit)
        animationEndListener?.onAnimationEnd(animation, canceled, value, velocity)
    }
suspend fun SpringAnimation.suspendAnimate(onAnimationUpdate: (Float) -> Unit) =
    suspendCancellableCoroutine { continuation ->
        val updateListener =
            DynamicAnimation.OnAnimationUpdateListener { _, value, _ -> onAnimationUpdate(value) }
        val endListener =
            DynamicAnimation.OnAnimationEndListener { _, _, _, _ -> continuation.resumeIfCan(Unit) }
        addUpdateListener(updateListener)
        addEndListener(endListener)
        animateToFinalPosition(1F)
        continuation.invokeOnCancellation {
        animationUpdateListener?.let(::removeUpdateListener)
        animationEndListener?.let(::removeEndListener)
            removeUpdateListener(updateListener)
            removeEndListener(endListener)
            cancel()
        }
    }