diff options
author | 2025-03-20 10:43:46 -0700 | |
---|---|---|
committer | 2025-03-20 10:43:46 -0700 | |
commit | c87ebdf3475d1385d00e51b71a19e1e48c7e2dea (patch) | |
tree | bb7ed3cfd5177c5a016247d9e45dc79a4223c185 | |
parent | 014ffc854c30c28bdbe17b61a1258d890f4b9419 (diff) | |
parent | a1fbc8da8d3dfde09e89adf131877961fe9d62c5 (diff) |
Merge "Center glanceable hub widgets vertically in the window" into main
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 |