summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Coco Duan <cocod@google.com> 2025-03-13 06:39:25 +0000
committer Coco Duan <cocod@google.com> 2025-03-20 01:02:26 +0000
commita1fbc8da8d3dfde09e89adf131877961fe9d62c5 (patch)
treecfa4f9e44e77e46d7fb029a8be9ddfee4143d2c0
parentc74a0961123efd89b350476e6d7a49b623e1d798 (diff)
Center glanceable hub widgets vertically in the window
Adjust grid padding and gutter values for compact screen sizes in portrait and landscape orientation. In CommunalContent, center communal grid vertically in window using even top and bottom margins. Bug: b/399688758 Test: on foldable and tablet Flag: com.android.systemui.communal_responsive_grid Change-Id: I3949d39b867b5bce1f0f6e42ac0c55bf40160941
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt23
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt74
2 files changed, 87 insertions, 10 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
index 0181928317e1..1a0fb0afd385 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt
@@ -16,6 +16,7 @@
package com.android.systemui.communal.ui.compose
+import android.content.res.Configuration
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -23,6 +24,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
+import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntRect
@@ -66,6 +68,7 @@ constructor(
@Composable
fun ContentScope.Content(modifier: Modifier = Modifier) {
CommunalTouchableSurface(viewModel = viewModel, modifier = modifier) {
+ val orientation = LocalConfiguration.current.orientation
Layout(
modifier = Modifier.fillMaxSize(),
content = {
@@ -150,13 +153,29 @@ constructor(
val bottomAreaPlaceable = bottomAreaMeasurable.measure(noMinConstraints)
+ val communalGridMaxHeight: Int
+ val communalGridPositionY: Int
+ if (Flags.communalResponsiveGrid()) {
+ val communalGridVerticalMargin = constraints.maxHeight - lockIconBounds.top
+ // Bias the widgets up by a small offset for visual balance in landscape
+ // orientation
+ val verticalOffset =
+ (if (orientation == Configuration.ORIENTATION_LANDSCAPE) (-3).dp else 0.dp)
+ .roundToPx()
+ // Use even top and bottom margin for grid to be centered in maxHeight (window)
+ communalGridMaxHeight = constraints.maxHeight - communalGridVerticalMargin * 2
+ communalGridPositionY = communalGridVerticalMargin + verticalOffset
+ } else {
+ communalGridMaxHeight = lockIconBounds.top
+ communalGridPositionY = 0
+ }
val communalGridPlaceable =
communalGridMeasurable.measure(
- noMinConstraints.copy(maxHeight = lockIconBounds.top)
+ noMinConstraints.copy(maxHeight = communalGridMaxHeight)
)
layout(constraints.maxWidth, constraints.maxHeight) {
- communalGridPlaceable.place(x = 0, y = 0)
+ communalGridPlaceable.place(x = 0, y = communalGridPositionY)
lockIconPlaceable.place(x = lockIconBounds.left, y = lockIconBounds.top)
val bottomAreaTop = constraints.maxHeight - bottomAreaPlaceable.height
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 835dd7aa9f24..ad2a32e030bb 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -54,7 +54,10 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.calculateStartPadding
+import androidx.compose.foundation.layout.displayCutout
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -76,8 +79,8 @@ import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.foundation.text.TextAutoSize
import androidx.compose.foundation.text.BasicText
+import androidx.compose.foundation.text.TextAutoSize
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
@@ -99,6 +102,8 @@ import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
+import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
+import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
@@ -174,6 +179,7 @@ import com.android.compose.animation.Easings.Emphasized
import com.android.compose.animation.scene.ContentScope
import com.android.compose.modifiers.thenIf
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
+import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.internal.R.dimen.system_app_widget_background_radius
import com.android.systemui.Flags
import com.android.systemui.Flags.communalResponsiveGrid
@@ -254,6 +260,7 @@ fun CommunalHub(
val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
val screenWidth = windowMetrics.bounds.width()
val layoutDirection = LocalLayoutDirection.current
+
if (viewModel.isEditMode) {
ObserveNewWidgetAddedEffect(communalContent, gridState, viewModel)
} else {
@@ -757,11 +764,33 @@ fun calculateWidgetSize(
}
@Composable
+private fun horizontalPaddingWithInsets(padding: Dp): Dp {
+ val orientation = LocalConfiguration.current.orientation
+ val displayCutoutPaddings = WindowInsets.displayCutout.asPaddingValues()
+ val horizontalDisplayCutoutPadding =
+ remember(orientation, displayCutoutPaddings) {
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ maxOf(
+ // Top in portrait becomes startPadding (or endPadding) in landscape
+ displayCutoutPaddings.calculateTopPadding(),
+ // Bottom in portrait becomes endPadding (or startPadding) in landscape
+ displayCutoutPaddings.calculateBottomPadding(),
+ )
+ } else {
+ 0.dp
+ }
+ }
+ return padding + horizontalDisplayCutoutPadding
+}
+
+@Composable
private fun HorizontalGridWrapper(
minContentPadding: PaddingValues,
gridState: LazyGridState,
dragDropState: GridDragDropState?,
setContentOffset: (offset: Offset) -> Unit,
+ minHorizontalArrangement: Dp,
+ minVerticalArrangement: Dp,
modifier: Modifier = Modifier,
content: LazyGridScope.(sizeInfo: SizeInfo?) -> Unit,
) {
@@ -775,8 +804,8 @@ private fun HorizontalGridWrapper(
state = gridState,
flingBehavior = flingBehavior,
minContentPadding = minContentPadding,
- minHorizontalArrangement = Dimensions.ItemSpacing,
- minVerticalArrangement = Dimensions.ItemSpacing,
+ minHorizontalArrangement = minHorizontalArrangement,
+ minVerticalArrangement = minVerticalArrangement,
setContentOffset = setContentOffset,
// Temporarily disable user gesture scrolling while dragging a widget to prevent
// conflicts between the drag and scroll gestures. Programmatic scrolling remains
@@ -833,6 +862,7 @@ private fun BoxScope.CommunalHubLazyGrid(
Modifier.align(Alignment.TopStart).onGloballyPositioned { setGridCoordinates(it) }
var list = communalContent
var dragDropState: GridDragDropState? = null
+ var arrangementSpacing = Dimensions.ItemSpacing
if (viewModel.isEditMode && viewModel is CommunalEditModeViewModel) {
list = contentListState.list
// for drag & drop operations within the communal hub grid
@@ -866,6 +896,9 @@ private fun BoxScope.CommunalHubLazyGrid(
Box(Modifier.fillMaxSize().dragAndDropTarget(dragAndDropTargetState)) {}
} else if (communalResponsiveGrid()) {
gridModifier = gridModifier.fillMaxSize()
+ if (isCompactWindow()) {
+ arrangementSpacing = Dimensions.ItemSpacingCompact
+ }
} else {
gridModifier = gridModifier.height(hubDimensions.GridHeight)
}
@@ -875,6 +908,8 @@ private fun BoxScope.CommunalHubLazyGrid(
gridState = gridState,
dragDropState = dragDropState,
minContentPadding = minContentPadding,
+ minHorizontalArrangement = arrangementSpacing,
+ minVerticalArrangement = arrangementSpacing,
setContentOffset = setContentOffset,
) { sizeInfo ->
/** Override spans based on the responsive grid size */
@@ -1839,11 +1874,21 @@ private fun nonScalableTextSize(sizeInDp: Dp) = with(LocalDensity.current) { siz
@Composable
private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): PaddingValues {
if (!isEditMode || toolbarSize == null) {
- return PaddingValues(
- start = Dimensions.ItemSpacing,
- end = Dimensions.ItemSpacing,
- top = hubDimensions.GridTopSpacing,
- )
+ return if (communalResponsiveGrid()) {
+ val horizontalPaddings: Dp =
+ if (isCompactWindow()) {
+ horizontalPaddingWithInsets(Dimensions.ItemSpacingCompact)
+ } else {
+ Dimensions.ItemSpacing
+ }
+ PaddingValues(start = horizontalPaddings, end = horizontalPaddings)
+ } else {
+ PaddingValues(
+ start = Dimensions.ItemSpacing,
+ end = Dimensions.ItemSpacing,
+ top = hubDimensions.GridTopSpacing,
+ )
+ }
}
val context = LocalContext.current
val density = LocalDensity.current
@@ -1870,6 +1915,16 @@ private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): Padd
}
}
+/** Compact size in landscape or portrait */
+@Composable
+fun isCompactWindow(): Boolean {
+ val windowSizeClass = LocalWindowSizeClass.current
+ return remember(windowSizeClass) {
+ windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact ||
+ windowSizeClass.heightSizeClass == WindowHeightSizeClass.Compact
+ }
+}
+
private fun CommunalContentSize.FixedSize.dp(): Dp {
return when (this) {
CommunalContentSize.FixedSize.FULL -> Dimensions.CardHeightFull
@@ -1911,6 +1966,9 @@ class Dimensions(val context: Context, val config: Configuration) {
val CardHeightFull
get() = 530.adjustedDp
+ val ItemSpacingCompact
+ get() = 12.adjustedDp
+
val ItemSpacing
get() = if (communalResponsiveGrid()) 32.adjustedDp else 50.adjustedDp