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

Commit f9d829a7 authored by Anton Potapov's avatar Anton Potapov
Browse files

Make UMO follow squishing QQS

Before this change UMO used an estimation of when the squishness looks
like, which sometimes was a bit off. Now UMO follows the actual height
of the QQS during the transition.

Flag: com.android.systemui.scene_container
Bug: 345467289
Bug: 353519527
Test: manual on the foldable, tablet and phone
Change-Id: I6b0c9188123292870d8e07945b9676bd3c065318
parent fc53eaec
Loading
Loading
Loading
Loading
+29 −9
Original line number Diff line number Diff line
@@ -24,9 +24,11 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.approachLayout
import androidx.compose.ui.layout.layout
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.viewinterop.AndroidView
import com.android.compose.animation.scene.MovableElementKey
import com.android.compose.animation.scene.SceneScope
@@ -51,6 +53,7 @@ fun SceneScope.MediaCarousel(
    mediaHost: MediaHost,
    modifier: Modifier = Modifier,
    carouselController: MediaCarouselController,
    offsetProvider: (() -> IntOffset)? = null,
) {
    if (!isVisible) {
        return
@@ -68,20 +71,37 @@ fun SceneScope.MediaCarousel(

    MovableElement(
        key = MediaCarousel.Elements.Content,
        modifier = modifier.height(mediaHeight).fillMaxWidth()
        modifier = modifier.height(mediaHeight).fillMaxWidth(),
    ) {
        content {
            AndroidView(
                modifier =
                    Modifier.fillMaxSize().layout { measurable, constraints ->
                    Modifier.fillMaxSize()
                        .approachLayout(
                            isMeasurementApproachInProgress = { offsetProvider != null },
                            approachMeasure = { measurable, constraints ->
                                val placeable = measurable.measure(constraints)
                                layout(placeable.width, placeable.height) {
                                    placeable.placeRelative(
                                        offsetProvider?.invoke() ?: IntOffset.Zero
                                    )
                                }
                            }
                        )
                        .layout { measurable, constraints ->
                            val placeable = measurable.measure(constraints)

                            // Notify controller to size the carousel for the current space
                            mediaHost.measurementInput =
                                MeasurementInput(placeable.width, placeable.height)
                        carouselController.setSceneContainerSize(placeable.width, placeable.height)
                            carouselController.setSceneContainerSize(
                                placeable.width,
                                placeable.height
                            )

                        layout(placeable.width, placeable.height) { placeable.placeRelative(0, 0) }
                            layout(placeable.width, placeable.height) {
                                placeable.placeRelative(0, 0)
                            }
                        },
                factory = { context ->
                    FrameLayout(context).apply {
+0 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import com.android.systemui.scene.shared.model.Scenes
/** [ElementContentPicker] implementation for the media carousel object. */
object MediaContentPicker : StaticElementContentPicker {

    const val SHADE_FRACTION = 0.66f
    override val contents =
        setOf(
            Scenes.Lockscreen,
+0 −7
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import com.android.compose.animation.scene.TransitionBuilder
import com.android.compose.animation.scene.UserActionDistance
import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.media.controls.ui.composable.MediaCarousel
import com.android.systemui.media.controls.ui.composable.MediaContentPicker
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.shade.ui.composable.Shade
@@ -54,13 +53,7 @@ fun TransitionBuilder.goneToSplitShadeTransition(
    fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) }

    fractionRange(start = .33f) {
        val qsTranslation =
            ShadeHeader.Dimensions.CollapsedHeight * MediaContentPicker.SHADE_FRACTION
        val qsExpansionDiff =
            ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight
        translate(MediaCarousel.Elements.Content, y = -(qsExpansionDiff + qsTranslation))
        fade(MediaCarousel.Elements.Content)

        fade(ShadeHeader.Elements.Clock)
        fade(ShadeHeader.Elements.CollapsedContentStart)
        fade(ShadeHeader.Elements.CollapsedContentEnd)
+3 −7
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import com.android.compose.animation.scene.TransitionBuilder
import com.android.compose.animation.scene.UserActionDistance
import com.android.compose.animation.scene.UserActionDistanceScope
import com.android.systemui.media.controls.ui.composable.MediaCarousel
import com.android.systemui.media.controls.ui.composable.MediaContentPicker
import com.android.systemui.notifications.ui.composable.Notifications
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.scene.shared.model.Scenes
@@ -62,12 +61,9 @@ fun TransitionBuilder.toShadeTransition(
        fade(QuickSettings.Elements.FooterActions)
    }

    val qsTranslation = ShadeHeader.Dimensions.CollapsedHeight * MediaContentPicker.SHADE_FRACTION
    val qsExpansionDiff =
        ShadeHeader.Dimensions.ExpandedHeight - ShadeHeader.Dimensions.CollapsedHeight

    translate(QuickSettings.Elements.QuickQuickSettings, y = -qsTranslation)
    translate(MediaCarousel.Elements.Content, y = -(qsExpansionDiff + qsTranslation))
    val qsTranslation = -ShadeHeader.Dimensions.CollapsedHeight * 0.66f
    translate(QuickSettings.Elements.QuickQuickSettings, y = qsTranslation)
    translate(MediaCarousel.Elements.Content, y = qsTranslation)
    translate(Notifications.Elements.NotificationScrim, Edge.Top, false)
}

+79 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.shade.ui.composable

import androidx.compose.ui.unit.IntOffset
import com.android.systemui.qs.ui.adapter.QSSceneAdapter

/**
 * Provider for the extra offset for the Media section in the shade to accommodate for the squishing
 * qs or qqs tiles.
 */
interface ShadeMediaOffsetProvider {

    /** Returns current offset to be applied to the Media Carousel */
    val offset: IntOffset

    /**
     * [ShadeMediaOffsetProvider] implementation for Quick Settings.
     *
     * [updateLayout] should represent an access to some state to trigger Compose to relayout to
     * track [QSSceneAdapter] internal state changes during the transition.
     */
    class Qs(private val updateLayout: () -> Unit, private val qsSceneAdapter: QSSceneAdapter) :
        ShadeMediaOffsetProvider {

        override val offset: IntOffset
            get() =
                calculateQsOffset(
                    updateLayout,
                    qsSceneAdapter.qsHeight,
                    qsSceneAdapter.squishedQsHeight
                )
    }

    /**
     * [ShadeMediaOffsetProvider] implementation for Quick Quick Settings.
     *
     * [updateLayout] should represent an access to some state to trigger Compose to relayout to
     * track [QSSceneAdapter] internal state changes during the transition.
     */
    class Qqs(private val updateLayout: () -> Unit, private val qsSceneAdapter: QSSceneAdapter) :
        ShadeMediaOffsetProvider {

        override val offset: IntOffset
            get() =
                calculateQsOffset(
                    updateLayout,
                    qsSceneAdapter.qqsHeight,
                    qsSceneAdapter.squishedQqsHeight
                )
    }

    companion object {

        protected fun calculateQsOffset(
            updateLayout: () -> Unit,
            qsHeight: Int,
            qsSquishedHeight: Int
        ): IntOffset {
            updateLayout()
            val distanceFromBottomToActualBottom = qsHeight - qsSquishedHeight
            return IntOffset(0, -distanceFromBottomToActualBottom)
        }
    }
}
Loading