summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabián Kozynski <kozynski@google.com> 2024-10-16 10:29:51 -0400
committer Fabián Kozynski <kozynski@google.com> 2024-10-16 10:34:52 -0400
commitc565bef9929dc4f02d391cffc9dbdd9e65ad6446 (patch)
treee5ab1634fb88ec5455d13ec0b7fe72799fcd1087
parent0a53b6c221de04d5068cc8ef73c072aa6b573240 (diff)
Implement translation animation
This is missing animateHeaderSlidingOut Test: manual Bug: 373382675 Flag: com.android.systemui.qs_ui_refactor_compose_fragment Change-Id: I0064c6a465105e3e7f77d8013475177512a0d950
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt48
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt65
2 files changed, 93 insertions, 20 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
index 3ea11026706d..f4d91627fdab 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
@@ -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,11 +236,15 @@ 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
viewModel.containerViewModel.editModeViewModel.isEditing
@@ -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() }
)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
index 408ea5243f7b..dd83fc928dad 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/viewmodel/QSFragmentComposeViewModel.kt
@@ -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