summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt38
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt24
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt103
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt13
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt8
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt55
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt15
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt50
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt13
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt2
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt41
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt2
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt21
17 files changed, 252 insertions, 194 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
index 52ccab3b4d1e..ec7e495ebe61 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/BottomAreaSection.kt
@@ -70,33 +70,29 @@ constructor(
key = if (isStart) StartButtonElementKey else EndButtonElementKey,
modifier = modifier,
) {
- content {
- Shortcut(
- viewId = if (isStart) R.id.start_button else R.id.end_button,
- viewModel = if (isStart) viewModel.startButton else viewModel.endButton,
- transitionAlpha = viewModel.transitionAlpha,
- indicationController = indicationController,
- binder = keyguardQuickAffordanceViewBinder,
- modifier =
- if (applyPadding) {
- Modifier.shortcutPadding()
- } else {
- Modifier
- },
- )
- }
+ Shortcut(
+ viewId = if (isStart) R.id.start_button else R.id.end_button,
+ viewModel = if (isStart) viewModel.startButton else viewModel.endButton,
+ transitionAlpha = viewModel.transitionAlpha,
+ indicationController = indicationController,
+ binder = keyguardQuickAffordanceViewBinder,
+ modifier =
+ if (applyPadding) {
+ Modifier.shortcutPadding()
+ } else {
+ Modifier
+ },
+ )
}
}
@Composable
fun ContentScope.IndicationArea(modifier: Modifier = Modifier) {
Element(key = IndicationAreaElementKey, modifier = modifier.indicationAreaPadding()) {
- content {
- IndicationArea(
- indicationAreaViewModel = indicationAreaViewModel,
- indicationController = indicationController,
- )
- }
+ IndicationArea(
+ indicationAreaViewModel = indicationAreaViewModel,
+ indicationController = indicationController,
+ )
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
index ae541dda6eeb..0583e8a0b1a2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
@@ -26,11 +26,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.key
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.viewinterop.AndroidView
-import androidx.core.view.contains
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ContentScope
import com.android.compose.modifiers.padding
@@ -132,18 +130,16 @@ constructor(
}
Element(key = largeClockElementKey, modifier = modifier) {
- content {
- ClockView(
- checkNotNull(currentClock).largeClock.view,
- modifier =
- Modifier.fillMaxSize()
- .burnInAware(
- viewModel = aodBurnInViewModel,
- params = burnInParams,
- isClock = true,
- ),
- )
- }
+ ClockView(
+ checkNotNull(currentClock).largeClock.view,
+ modifier =
+ Modifier.fillMaxSize()
+ .burnInAware(
+ viewModel = aodBurnInViewModel,
+ params = burnInParams,
+ isClock = true,
+ ),
+ )
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
index c3ba7ab2fd19..c7b797dfa0a2 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/SmartSpaceSection.kt
@@ -66,64 +66,61 @@ constructor(
val resources = LocalContext.current.resources
Element(key = ClockElementKeys.smartspaceElementKey, modifier = modifier) {
- content {
- Column(
- modifier =
- modifier
- .onTopPlacementChanged(onTopChanged)
- .padding(
- top = { smartSpacePaddingTop(resources) },
- bottom = {
- resources.getDimensionPixelSize(
- R.dimen.keyguard_status_view_bottom_margin
- )
- },
- )
- ) {
- if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) {
- return@Column
- }
-
- val paddingBelowClockStart =
- dimensionResource(R.dimen.below_clock_padding_start)
- val paddingBelowClockEnd = dimensionResource(R.dimen.below_clock_padding_end)
- val paddingCardHorizontal = paddingBelowClockEnd
+ Column(
+ modifier =
+ modifier
+ .onTopPlacementChanged(onTopChanged)
+ .padding(
+ top = { smartSpacePaddingTop(resources) },
+ bottom = {
+ resources.getDimensionPixelSize(
+ R.dimen.keyguard_status_view_bottom_margin
+ )
+ },
+ )
+ ) {
+ if (!keyguardSmartspaceViewModel.isSmartspaceEnabled) {
+ return@Column
+ }
- if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
- Row(
- verticalAlignment = Alignment.CenterVertically,
- modifier =
- Modifier.fillMaxWidth()
- // All items will be constrained to be as tall as the shortest
- // item.
- .height(IntrinsicSize.Min)
- .padding(start = paddingBelowClockStart),
- ) {
- Date(
- modifier =
- Modifier.burnInAware(
- viewModel = aodBurnInViewModel,
- params = burnInParams,
- )
- )
- Spacer(modifier = Modifier.width(4.dp))
- Weather(
- modifier =
- Modifier.burnInAware(
- viewModel = aodBurnInViewModel,
- params = burnInParams,
- )
- )
- }
- }
+ val paddingBelowClockStart = dimensionResource(R.dimen.below_clock_padding_start)
+ val paddingBelowClockEnd = dimensionResource(R.dimen.below_clock_padding_end)
+ val paddingCardHorizontal = paddingBelowClockEnd
- Card(
+ if (keyguardSmartspaceViewModel.isDateWeatherDecoupled) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
modifier =
Modifier.fillMaxWidth()
- .padding(start = paddingCardHorizontal, end = paddingCardHorizontal)
- .burnInAware(viewModel = aodBurnInViewModel, params = burnInParams)
- )
+ // All items will be constrained to be as tall as the shortest
+ // item.
+ .height(IntrinsicSize.Min)
+ .padding(start = paddingBelowClockStart),
+ ) {
+ Date(
+ modifier =
+ Modifier.burnInAware(
+ viewModel = aodBurnInViewModel,
+ params = burnInParams,
+ )
+ )
+ Spacer(modifier = Modifier.width(4.dp))
+ Weather(
+ modifier =
+ Modifier.burnInAware(
+ viewModel = aodBurnInViewModel,
+ params = burnInParams,
+ )
+ )
+ }
}
+
+ Card(
+ modifier =
+ Modifier.fillMaxWidth()
+ .padding(start = paddingCardHorizontal, end = paddingCardHorizontal)
+ .burnInAware(viewModel = aodBurnInViewModel, params = burnInParams)
+ )
}
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
index 4fcb5ca42df2..a8b2b13d53be 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/WeatherClockSection.kt
@@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.key
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
@@ -109,14 +108,10 @@ constructor(
modifier: Modifier = Modifier,
) {
Element(key = elementKey, modifier) {
- content {
- ClockView(
- clock.largeClock.layout.views.firstOrNull {
- it.id == weatherClockElementViewId
- },
- modifier,
- )
- }
+ ClockView(
+ clock.largeClock.layout.views.firstOrNull { it.id == weatherClockElementViewId },
+ modifier,
+ )
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
index 9c85c96c4666..60c017227334 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/footer/ui/compose/FooterActions.kt
@@ -116,11 +116,9 @@ fun ContentScope.FooterActionsWithAnimatedVisibility(
QuickSettingsTheme {
// This view has its own horizontal padding
// TODO(b/321716470) This should use a lifecycle tied to the scene.
- FooterActions(
- viewModel = viewModel,
- qsVisibilityLifecycleOwner = lifecycleOwner,
- modifier = Modifier.element(QuickSettings.Elements.FooterActions),
- )
+ Element(QuickSettings.Elements.FooterActions, Modifier) {
+ FooterActions(viewModel = viewModel, qsVisibilityLifecycleOwner = lifecycleOwner)
+ }
}
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index db9035b1635b..23baeacd76ec 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -440,33 +440,36 @@ private fun CutoutAwareShadeHeader(
private fun ContentScope.Clock(scale: Float, onClick: () -> Unit, modifier: Modifier = Modifier) {
val layoutDirection = LocalLayoutDirection.current
- Element(key = ShadeHeader.Elements.Clock, modifier = modifier) {
+ ElementWithValues(key = ShadeHeader.Elements.Clock, modifier = modifier) {
val animatedScale by animateElementFloatAsState(scale, ClockScale, canOverflow = false)
- AndroidView(
- factory = { context ->
- Clock(
- ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings_Header),
- null,
- )
- },
- modifier =
- modifier
- // use graphicsLayer instead of Modifier.scale to anchor transform
- // to the (start, top) corner
- .graphicsLayer {
- scaleX = animatedScale
- scaleY = animatedScale
- transformOrigin =
- TransformOrigin(
- when (layoutDirection) {
- LayoutDirection.Ltr -> 0f
- LayoutDirection.Rtl -> 1f
- },
- 0.5f,
- )
- }
- .clickable { onClick() },
- )
+
+ content {
+ AndroidView(
+ factory = { context ->
+ Clock(
+ ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings_Header),
+ null,
+ )
+ },
+ modifier =
+ modifier
+ // use graphicsLayer instead of Modifier.scale to anchor transform to the
+ // (start, top) corner
+ .graphicsLayer {
+ scaleX = animatedScale
+ scaleY = animatedScale
+ transformOrigin =
+ TransformOrigin(
+ when (layoutDirection) {
+ LayoutDirection.Ltr -> 0f
+ LayoutDirection.Rtl -> 1f
+ },
+ 0.5f,
+ )
+ }
+ .clickable { onClick() },
+ )
+ }
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index f4af5f055935..eab5206d0ec5 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -35,6 +35,21 @@ internal fun Element(
sceneOrOverlay: Content,
key: ElementKey,
modifier: Modifier,
+ content: @Composable BoxScope.() -> Unit,
+) {
+ Box(
+ modifier.element(layoutImpl, sceneOrOverlay, key),
+ propagateMinConstraints = true,
+ content = content,
+ )
+}
+
+@Composable
+internal fun ElementWithValues(
+ layoutImpl: SceneTransitionLayoutImpl,
+ sceneOrOverlay: Content,
+ key: ElementKey,
+ modifier: Modifier,
content: @Composable ElementScope<ElementContentScope>.() -> Unit,
) {
Box(modifier.element(layoutImpl, sceneOrOverlay, key), propagateMinConstraints = true) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index f423bab5381f..53d0ee1d2045 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -22,6 +22,7 @@ import androidx.compose.foundation.LocalOverscrollFactory
import androidx.compose.foundation.OverscrollEffect
import androidx.compose.foundation.OverscrollFactory
import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.Stable
@@ -188,7 +189,7 @@ interface BaseContentScope : ElementStateScope {
* Additionally, this [key] will be used to detect elements that are shared between contents to
* automatically interpolate their size and offset. If you need to animate shared element values
* (i.e. values associated to this element that change depending on which content it is composed
- * in), use [Element] instead.
+ * in), use [ElementWithValues] instead.
*
* Note that shared elements tagged using this function will be duplicated in each content they
* are part of, so any **internal** state (e.g. state created using `remember {
@@ -196,9 +197,12 @@ interface BaseContentScope : ElementStateScope {
* [MovableElement] instead.
*
* @see Element
+ * @see ElementWithValues
* @see MovableElement
*/
- fun Modifier.element(key: ElementKey): Modifier
+ // TODO(b/389985793): Does replacing this by Element have a noticeable impact on performance and
+ // should we deprecate it?
+ @Stable fun Modifier.element(key: ElementKey): Modifier
/**
* Create an element identified by [key].
@@ -207,17 +211,29 @@ interface BaseContentScope : ElementStateScope {
* in multiple contents and that can be transformed during transitions, the same way that
* [element] does.
*
- * The only difference with [element] is that the provided [ElementScope] allows you to
- * [animate element values][ElementScope.animateElementValueAsState] or specify its
- * [movable content][Element.movableContent] that will be "moved" and composed only once during
- * transitions (as opposed to [element] that duplicates shared elements) so that any internal
- * state is preserved during and after the transition.
+ * The only difference with [element] is that [Element] introduces its own recomposition scope
+ * and layout node, which can be helpful to avoid expensive recompositions when a transition is
+ * started or finished (see b/389985793#comment103 for details).
*
* @see element
+ * @see ElementWithValues
* @see MovableElement
*/
@Composable
- fun Element(
+ fun Element(key: ElementKey, modifier: Modifier, content: @Composable BoxScope.() -> Unit)
+
+ /**
+ * Create an element identified by [key].
+ *
+ * The only difference with [Element] is that the provided [ElementScope] allows you to
+ * [animate element values][ElementScope.animateElementValueAsState].
+ *
+ * @see element
+ * @see Element
+ * @see MovableElement
+ */
+ @Composable
+ fun ElementWithValues(
key: ElementKey,
modifier: Modifier,
@@ -230,17 +246,19 @@ interface BaseContentScope : ElementStateScope {
/**
* Create a *movable* element identified by [key].
*
- * Similar to [Element], this creates an element that will be automatically shared when present
- * in multiple contents and that can be transformed during transitions, and you can also use the
- * provided [ElementScope] to [animate element values][ElementScope.animateElementValueAsState].
+ * Similar to [ElementWithValues], this creates an element that will be automatically shared
+ * when present in multiple contents and that can be transformed during transitions, and you can
+ * also use the provided [ElementScope] to
+ * [animate element values][ElementScope.animateElementValueAsState].
*
- * The important difference with [element] and [Element] is that this element
- * [content][ElementScope.content] will be "moved" and composed only once during transitions, as
- * opposed to [element] and [Element] that duplicates shared elements, so that any internal
- * state is preserved during and after the transition.
+ * The important difference with [element], [Element] and [ElementWithValues] is that this
+ * element [content][ElementScope.content] will be "moved" and composed only once during
+ * transitions, as opposed to [element], [Element] and [ElementWithValues] that duplicates
+ * shared elements, so that any internal state is preserved during and after the transition.
*
* @see element
* @see Element
+ * @see ElementWithValues
*/
@Composable
fun MovableElement(
@@ -415,7 +433,7 @@ interface ElementScope<ContentScope> {
*
* We can't reuse BoxScope directly because of the @LayoutScopeMarker annotation on it, which would
* prevent us from calling Modifier.element() and other methods of [ContentScope] inside any Box {}
- * in the [content][ElementScope.content] of a [ContentScope.Element] or a
+ * in the [content][ElementScope.content] of a [ContentScope.ElementWithValues] or a
* [ContentScope.MovableElement].
*/
@Stable
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
index 95d6440d585e..9ca45fe92ad5 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt
@@ -21,6 +21,7 @@ import androidx.compose.foundation.LocalOverscrollFactory
import androidx.compose.foundation.OverscrollEffect
import androidx.compose.foundation.OverscrollFactory
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
@@ -45,6 +46,7 @@ import com.android.compose.animation.scene.ElementContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementScope
import com.android.compose.animation.scene.ElementStateScope
+import com.android.compose.animation.scene.ElementWithValues
import com.android.compose.animation.scene.InternalContentScope
import com.android.compose.animation.scene.MovableElement
import com.android.compose.animation.scene.MovableElementContentScope
@@ -222,12 +224,21 @@ internal class ContentScopeImpl(
override fun Element(
key: ElementKey,
modifier: Modifier,
- content: @Composable (ElementScope<ElementContentScope>.() -> Unit),
+ content: @Composable BoxScope.() -> Unit,
) {
Element(layoutImpl, this@ContentScopeImpl.content, key, modifier, content)
}
@Composable
+ override fun ElementWithValues(
+ key: ElementKey,
+ modifier: Modifier,
+ content: @Composable (ElementScope<ElementContentScope>.() -> Unit),
+ ) {
+ ElementWithValues(layoutImpl, this@ContentScopeImpl.content, key, modifier, content)
+ }
+
+ @Composable
override fun MovableElement(
key: MovableElementKey,
modifier: Modifier,
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
index d11e6da18ed0..d06e040f11e7 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
@@ -67,7 +67,7 @@ class AnimatedSharedAsStateTest {
@Composable
private fun ContentScope.Foo(targetValues: Values, onCurrentValueChanged: (Values) -> Unit) {
val key = TestElements.Foo
- Element(key, Modifier) {
+ ElementWithValues(key, Modifier) {
val int by animateElementIntAsState(targetValues.int, key = TestValues.Value1)
val float by animateElementFloatAsState(targetValues.float, key = TestValues.Value2)
val dp by animateElementDpAsState(targetValues.dp, key = TestValues.Value3)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index 698a80829284..338fb9b674a1 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -1163,7 +1163,7 @@ class ElementTest {
@Composable
fun ContentScope.Foo(size: Dp, value: Float, modifier: Modifier = Modifier) {
val contentKey = this.contentKey
- Element(TestElements.Foo, modifier.size(size)) {
+ ElementWithValues(TestElements.Foo, modifier.size(size)) {
val animatedValue = animateElementFloatAsState(value, TestValues.Value1)
LaunchedEffect(animatedValue) {
snapshotFlow { animatedValue.value }.collect { lastValues[contentKey] = it }
@@ -2090,11 +2090,9 @@ class ElementTest {
TestContentScope(currentScene = SceneA) {
Column {
Element(TestElements.Foo, Modifier.size(40.dp)) {
- content {
- // Modifier.size() sets a preferred size and this should be ignored
- // because of the previously set 40dp size.
- Box(Modifier.testTag(contentTestTag).size(20.dp))
- }
+ // Modifier.size() sets a preferred size and this should be ignored because
+ // of the previously set 40dp size.
+ Box(Modifier.testTag(contentTestTag).size(20.dp))
}
MovableElement(movable, Modifier.size(40.dp)) {
@@ -2283,4 +2281,35 @@ class ElementTest {
.assertSizeIsEqualTo(50.dp)
.assertPositionInRootIsEqualTo(100.dp, 100.dp)
}
+
+ @Test
+ fun elementContentIsNotRecomposedWhenATransitionStarts() {
+ var compositions = 0
+ val state = rule.runOnUiThread { MutableSceneTransitionLayoutStateForTests(SceneA) }
+ val scope =
+ rule.setContentAndCreateMainScope {
+ SceneTransitionLayoutForTesting(state) {
+ scene(SceneA) {
+ Box(Modifier.fillMaxSize()) {
+ Element(TestElements.Foo, Modifier) { SideEffect { compositions++ } }
+ }
+ }
+ scene(SceneB) { Box(Modifier.fillMaxSize()) }
+ scene(SceneC) { Box(Modifier.fillMaxSize()) }
+ }
+ }
+
+ assertThat(compositions).isEqualTo(1)
+
+ scope.launch { state.startTransition(transition(SceneA, SceneB)) }
+ rule.waitForIdle()
+
+ scope.launch { state.startTransition(transition(SceneA, SceneC)) }
+ rule.waitForIdle()
+
+ scope.launch { state.startTransition(transition(SceneA, SceneB)) }
+ rule.waitForIdle()
+
+ assertThat(compositions).isEqualTo(1)
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
index e023936eb448..ebbde702c604 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
@@ -313,7 +313,7 @@ class MovableElementTest {
fun elementScopeExtendsBoxScope() {
rule.setContent {
TestContentScope {
- Element(TestElements.Foo, Modifier.size(200.dp)) {
+ ElementWithValues(TestElements.Foo, Modifier.size(200.dp)) {
content {
Box {
Box(Modifier.testTag("bottomEnd").align(Alignment.BottomEnd))
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index 3578be4b36a7..d7f7a514682c 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -129,7 +129,7 @@ class SceneTransitionLayoutTest {
@Composable
private fun ContentScope.SharedFoo(size: Dp, childOffset: Dp, modifier: Modifier = Modifier) {
- Element(TestElements.Foo, modifier.size(size).background(Color.Red)) {
+ ElementWithValues(TestElements.Foo, modifier.size(size).background(Color.Red)) {
// Offset the single child of Foo by some animated shared offset.
val offset by animateElementDpAsState(childOffset, TestValues.Value1)
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 6ad8bae05d7a..71eacdf05cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
@@ -312,20 +312,18 @@ constructor(
SceneTransitionLayout(state = sceneState, modifier = Modifier.fillMaxSize()) {
scene(QuickSettings) {
LaunchedEffect(Unit) { viewModel.onQSOpen() }
- QuickSettingsElement(Modifier.element(QuickSettings.rootElementKey))
+ Element(QuickSettings.rootElementKey, Modifier) { QuickSettingsElement() }
}
scene(QuickQuickSettings) {
LaunchedEffect(Unit) { viewModel.onQQSOpen() }
// Cannot pass the element modifier in because the top element has a `testTag`
// and this would overwrite it.
- Box(Modifier.element(QuickQuickSettings.rootElementKey)) {
- QuickQuickSettingsElement()
- }
+ Element(QuickQuickSettings.rootElementKey, Modifier) { QuickQuickSettingsElement() }
}
scene(SceneKeys.EditMode) {
- EditModeElement(Modifier.element(SceneKeys.EditMode.rootElementKey))
+ Element(SceneKeys.EditMode.rootElementKey, Modifier) { EditModeElement() }
}
}
}
@@ -656,10 +654,7 @@ constructor(
)
) {
if (viewModel.isQsEnabled) {
- Box(
- modifier =
- Modifier.element(ElementKeys.QuickSettingsContent).fillMaxSize().weight(1f)
- ) {
+ Element(ElementKeys.QuickSettingsContent, modifier = Modifier.weight(1f)) {
DisposableEffect(Unit) {
lifecycleScope.launch { scrollState.scrollTo(0) }
onDispose { lifecycleScope.launch { scrollState.scrollTo(0) } }
@@ -667,7 +662,8 @@ constructor(
Column(
modifier =
- Modifier.onPlaced { coordinates ->
+ Modifier.fillMaxSize()
+ .onPlaced { coordinates ->
val positionOnScreen = coordinates.positionOnScreen()
val left = positionOnScreen.x
val right = left + coordinates.size.width
@@ -744,13 +740,15 @@ constructor(
}
}
QuickSettingsTheme {
- FooterActions(
- viewModel = viewModel.footerActionsViewModel,
- qsVisibilityLifecycleOwner = this@QSFragmentCompose,
- modifier =
- Modifier.sysuiResTag(ResIdTags.qsFooterActions)
- .element(ElementKeys.FooterActions),
- )
+ Element(
+ ElementKeys.FooterActions,
+ Modifier.sysuiResTag(ResIdTags.qsFooterActions),
+ ) {
+ FooterActions(
+ viewModel = viewModel.footerActionsViewModel,
+ qsVisibilityLifecycleOwner = this@QSFragmentCompose,
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
index 266e875df85a..19ad9fcd4495 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/ui/GridAnchor.kt
@@ -16,7 +16,6 @@
package com.android.systemui.qs.composefragment.ui
-import androidx.compose.foundation.layout.Spacer
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.ContentScope
@@ -29,5 +28,5 @@ import com.android.systemui.qs.shared.ui.ElementKeys
@Composable
fun ContentScope.GridAnchor(modifier: Modifier = Modifier) {
// The size of this anchor does not matter, as the tiles don't change size on expansion.
- Spacer(modifier.element(ElementKeys.GridAnchor))
+ Element(ElementKeys.GridAnchor, modifier) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
index b084f79a5bba..495870f0a978 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/QuickQuickSettings.kt
@@ -71,17 +71,19 @@ fun ContentScope.QuickQuickSettings(
val it = sizedTiles[spanIndex]
val column = cellIndex % columns
cellIndex += it.width
- Tile(
- tile = it.tile,
- iconOnly = it.isIcon,
- modifier = Modifier.element(it.tile.spec.toElementKey(spanIndex)),
- squishiness = { squishiness },
- coroutineScope = scope,
- bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
- tileHapticsViewModelFactoryProvider = viewModel.tileHapticsViewModelFactoryProvider,
- // There should be no QuickQuickSettings when the details view is enabled.
- detailsViewModel = null,
- )
+ Element(it.tile.spec.toElementKey(spanIndex), Modifier) {
+ Tile(
+ tile = it.tile,
+ iconOnly = it.isIcon,
+ squishiness = { squishiness },
+ coroutineScope = scope,
+ bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
+ tileHapticsViewModelFactoryProvider =
+ viewModel.tileHapticsViewModelFactoryProvider,
+ // There should be no QuickQuickSettings when the details view is enabled.
+ detailsViewModel = null,
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
index 1c540eed8aa0..dfee497655d1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
@@ -99,16 +99,17 @@ constructor(
val it = sizedTiles[spanIndex]
val column = cellIndex % columns
cellIndex += it.width
- Tile(
- tile = it.tile,
- iconOnly = iconTilesViewModel.isIconTile(it.tile.spec),
- modifier = Modifier.element(it.tile.spec.toElementKey(spanIndex)),
- squishiness = { squishiness },
- tileHapticsViewModelFactoryProvider = tileHapticsViewModelFactoryProvider,
- coroutineScope = scope,
- bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
- detailsViewModel = detailsViewModel,
- )
+ Element(it.tile.spec.toElementKey(spanIndex), Modifier) {
+ Tile(
+ tile = it.tile,
+ iconOnly = iconTilesViewModel.isIconTile(it.tile.spec),
+ squishiness = { squishiness },
+ tileHapticsViewModelFactoryProvider = tileHapticsViewModelFactoryProvider,
+ coroutineScope = scope,
+ bounceableInfo = bounceables.bounceableInfo(it, spanIndex, column, columns),
+ detailsViewModel = detailsViewModel,
+ )
+ }
}
}