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

Commit c565bef9 authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

Implement translation animation

This is missing animateHeaderSlidingOut

Test: manual
Bug: 373382675
Flag: com.android.systemui.qs_ui_refactor_compose_fragment

Change-Id: I0064c6a465105e3e7f77d8013475177512a0d950
parent 0a53b6c2
Loading
Loading
Loading
Loading
+31 −17
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
@@ -59,6 +60,7 @@ import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.approachLayout
import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.dimensionResource
@@ -66,7 +68,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.round
import androidx.compose.ui.util.fastRoundToInt
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
@@ -144,9 +148,6 @@ constructor(

    private lateinit var viewModel: QSFragmentComposeViewModel

    // Starting with a non-zero value makes it so that it has a non-zero height on first expansion
    // This is important for `QuickSettingsControllerImpl.mMinExpansionHeight` to detect a "change".
    private val qqsHeight = MutableStateFlow(1)
    private val qsHeight = MutableStateFlow(0)
    private val qqsVisible = MutableStateFlow(false)
    private val qqsPositionOnRoot = Rect()
@@ -235,10 +236,14 @@ constructor(
            AnimatedVisibility(
                visible = viewModel.isQsVisible,
                modifier =
                    Modifier.windowInsetsPadding(WindowInsets.navigationBars).thenIf(
                        notificationScrimClippingParams.isEnabled
                    ) {
                        Modifier.notificationScrimClip { notificationScrimClippingParams.params }
                    Modifier.windowInsetsPadding(WindowInsets.navigationBars)
                        .thenIf(notificationScrimClippingParams.isEnabled) {
                            Modifier.notificationScrimClip {
                                notificationScrimClippingParams.params
                            }
                        }
                        .offset {
                            IntOffset(x = 0, y = viewModel.viewTranslationY.fastRoundToInt())
                        },
            ) {
                val isEditing by
@@ -317,7 +322,7 @@ constructor(

    override fun getQsMinExpansionHeight(): Int {
        // TODO (b/353253277) implement split screen
        return qqsHeight.value
        return viewModel.qqsHeight
    }

    override fun getDesiredHeight(): Int {
@@ -383,8 +388,7 @@ constructor(
        viewModel.setQsExpansionValue(qsExpansionFraction)
        viewModel.panelExpansionFraction = panelExpansionFraction
        viewModel.squishinessFraction = squishinessFraction

        // TODO(b/353254353) Handle header translation
        viewModel.proposedTranslation = headerTranslation
    }

    override fun setHeaderListening(listening: Boolean) {
@@ -404,7 +408,7 @@ constructor(
    }

    override fun getHeightDiff(): Int {
        return 0 // For now TODO(b/353254353)
        return viewModel.heightDiff
    }

    override fun getHeader(): View? {
@@ -466,7 +470,7 @@ constructor(
    }

    override fun setOverScrollAmount(overScrollAmount: Int) {
        super.setOverScrollAmount(overScrollAmount)
        viewModel.overScrollAmount = overScrollAmount
    }

    override fun setIsNotificationPanelFullWidth(isFullWidth: Boolean) {
@@ -525,7 +529,7 @@ constructor(
    @Composable
    private fun SceneScope.QuickQuickSettingsElement() {
        val qqsPadding = viewModel.qqsHeaderHeight
        val bottomPadding = dimensionResource(id = R.dimen.qqs_layout_padding_bottom)
        val bottomPadding = viewModel.qqsBottomPadding
        DisposableEffect(Unit) {
            qqsVisible.value = true

@@ -555,11 +559,11 @@ constructor(
                        .approachLayout(isMeasurementApproachInProgress = { squishiness < 1f }) {
                            measurable,
                            constraints ->
                            qqsHeight.value = lookaheadSize.height
                            viewModel.qqsHeight = lookaheadSize.height
                            val placeable = measurable.measure(constraints)
                            layout(placeable.width, placeable.height) { placeable.place(0, 0) }
                        }
                        .padding(top = { qqsPadding }, bottom = { bottomPadding.roundToPx() })
                        .padding(top = { qqsPadding }, bottom = { bottomPadding })
            ) {
                if (viewModel.isQsEnabled) {
                    QuickQuickSettings(
@@ -602,7 +606,17 @@ constructor(
                        onDispose { lifecycleScope.launch { scrollState.scrollTo(0) } }
                    }

                    Column(modifier = Modifier.verticalScroll(scrollState)) {
                    Column(
                        modifier =
                            Modifier.offset {
                                    IntOffset(
                                        x = 0,
                                        y = viewModel.qsScrollTranslationY.fastRoundToInt(),
                                    )
                                }
                                .onSizeChanged { viewModel.qsScrollHeight = it.height }
                                .verticalScroll(scrollState)
                    ) {
                        Spacer(
                            modifier = Modifier.height { qqsPadding + qsExtraPadding.roundToPx() }
                        )
+62 −3
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.qs.panels.domain.interactor.TileSquishinessInteractor
import com.android.systemui.qs.panels.ui.viewmodel.PaginatedGridViewModel
import com.android.systemui.qs.ui.viewmodel.QuickSettingsContainerViewModel
import com.android.systemui.res.R
import com.android.systemui.shade.LargeScreenHeaderHelper
import com.android.systemui.shade.transition.LargeScreenShadeInterpolator
import com.android.systemui.statusbar.StatusBarState
@@ -123,8 +124,26 @@ constructor(
                },
        )

    val qqsBottomPadding by
        hydrator.hydratedStateOf(
            traceName = "qqsBottomPadding",
            initialValue = resources.getDimensionPixelSize(R.dimen.qqs_layout_padding_bottom),
            source = configurationInteractor.dimensionPixelSize(R.dimen.qqs_layout_padding_bottom),
        )

    // Starting with a non-zero value makes it so that it has a non-zero height on first expansion
    // This is important for `QuickSettingsControllerImpl.mMinExpansionHeight` to detect a "change".
    var qqsHeight by mutableStateOf(1)

    var qsScrollHeight by mutableStateOf(0)

    val heightDiff: Int
        get() = qsScrollHeight - qqsHeight + qqsBottomPadding

    var isStackScrollerOverscrolling by mutableStateOf(false)

    var proposedTranslation by mutableStateOf(0f)

    /**
     * Whether QS is enabled by policy. This is normally true, except when it's disabled by some
     * policy. See [DisableFlagsRepository].
@@ -165,6 +184,25 @@ constructor(
    val inFirstPage: Boolean
        get() = paginatedGridViewModel.inFirstPage

    var overScrollAmount by mutableStateOf(0)

    val viewTranslationY by derivedStateOf {
        if (isOverscrolling) {
            overScrollAmount.toFloat()
        } else {
            if (onKeyguardAndExpanded) {
                translationScaleY * qqsHeight
            } else {
                headerTranslation
            }
        }
    }

    val qsScrollTranslationY by derivedStateOf {
        val panelTranslationY = translationScaleY * heightDiff
        if (onKeyguardAndExpanded) panelTranslationY else 0f
    }

    private var qsBounds by mutableStateOf(Rect())

    private val constrainedSquishinessFraction: Float
@@ -209,8 +247,6 @@ constructor(

    private var viewHeight by mutableStateOf(0)

    private var headerTranslation by mutableStateOf(0f)

    private val isBypassEnabled by
        hydrator.hydratedStateOf(
            traceName = "isBypassEnabled",
@@ -221,7 +257,11 @@ constructor(
        isBypassEnabled || (isTransitioningToFullShade && !isInSplitShade)
    }

    private var overscrolling = mutableStateOf(false)
    private val onKeyguardAndExpanded: Boolean
        get() = isKeyguardState && !showCollapsedOnKeyguard

    private val isOverscrolling: Boolean
        get() = overScrollAmount != 0

    private var shouldUpdateMediaSquishiness by mutableStateOf(false)

@@ -230,6 +270,13 @@ constructor(
            (isKeyguardState && !showCollapsedOnKeyguard)
    }

    private val translationScaleY: Float
        get() = (qsExpansion - 1) * (if (isInSplitShade) 1f else SHORT_PARALLAX_AMOUNT)

    private val headerTranslation by derivedStateOf {
        if (isTransitioningToFullShade) 0f else proposedTranslation
    }

    override suspend fun onActivated(): Nothing {
        coroutineScope {
            launch { hydrateSquishinessInteractor() }
@@ -255,8 +302,15 @@ constructor(
                println("qsExpansion", qsExpansion)
                println("panelExpansionFraction", panelExpansionFraction)
                println("squishinessFraction", squishinessFraction)
                println("proposedTranslation", proposedTranslation)
                println("expansionState", expansionState)
                println("forceQS", forceQs)
                printSection("Derived values") {
                    println("headerTranslation", headerTranslation)
                    println("translationScaleY", translationScaleY)
                    println("viewTranslationY", viewTranslationY)
                    println("qsScrollTranslationY", qsScrollTranslationY)
                }
            }
            printSection("Shade state") {
                println("stackOverscrolling", isStackScrollerOverscrolling)
@@ -265,8 +319,11 @@ constructor(
                println("isSmallScreen", isSmallScreen)
                println("heightOverride", "${heightOverride}px")
                println("qqsHeaderHeight", "${qqsHeaderHeight}px")
                println("qqsBottomPadding", "${qqsBottomPadding}px")
                println("isSplitShade", isInSplitShade)
                println("showCollapsedOnKeyguard", showCollapsedOnKeyguard)
                println("qqsHeight", "${qqsHeight}px")
                println("qsScrollHeight", "${qsScrollHeight}px")
            }
        }
    }
@@ -283,3 +340,5 @@ constructor(
private fun Float.constrainSquishiness(): Float {
    return (0.1f + this * 0.9f).coerceIn(0f, 1f)
}

private val SHORT_PARALLAX_AMOUNT = 0.1f