Loading packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt +21 −2 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 = { Loading Loading @@ -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 Loading packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +66 −8 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 { Loading Loading @@ -756,12 +763,34 @@ 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, ) { Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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) } Loading @@ -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 */ Loading Loading @@ -1839,12 +1874,22 @@ private fun nonScalableTextSize(sizeInDp: Dp) = with(LocalDensity.current) { siz @Composable private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): PaddingValues { if (!isEditMode || toolbarSize == null) { return PaddingValues( 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 val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context) Loading @@ -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 Loading Loading @@ -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 Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContent.kt +21 −2 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 = { Loading Loading @@ -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 Loading
packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +66 −8 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 { Loading Loading @@ -756,12 +763,34 @@ 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, ) { Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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) } Loading @@ -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 */ Loading Loading @@ -1839,12 +1874,22 @@ private fun nonScalableTextSize(sizeInDp: Dp) = with(LocalDensity.current) { siz @Composable private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): PaddingValues { if (!isEditMode || toolbarSize == null) { return PaddingValues( 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 val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context) Loading @@ -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 Loading Loading @@ -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 Loading