Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c87ebdf3 authored by Coco Duan's avatar Coco Duan Committed by Android (Google) Code Review
Browse files

Merge "Center glanceable hub widgets vertically in the window" into main

parents 014ffc85 a1fbc8da
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -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
+66 −8
Original line number Diff line number Diff line
@@ -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 {
@@ -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,
) {
@@ -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,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)
@@ -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