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

Commit 7bbc29a7 authored by Lucas Silva's avatar Lucas Silva
Browse files

Fix responsive grid in edit mode and content padding.

The content padding is dynamic based on the available space for the
grid. Therefore we introduce a way to set the content offset from the
grid, such that it can be used for touch handling.

Bug: 378171351
Test: manually by entering edit mode in portrait and landscape with
responsive enabled.
Flag: com.android.systemui.communal_responsive_grid

Change-Id: I2eca45db33cfaa3ae8717002b1adfcd6c035c054
parent 901496fd
Loading
Loading
Loading
Loading
+39 −33
Original line number Diff line number Diff line
@@ -218,6 +218,7 @@ fun CommunalHub(
    var removeButtonCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
    var toolbarSize: IntSize? by remember { mutableStateOf(null) }
    var gridCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
    var contentOffset: Offset by remember { mutableStateOf(Offset.Zero) }

    val gridState =
        rememberLazyGridState(viewModel.savedFirstScrollIndex, viewModel.savedFirstScrollOffset)
@@ -240,9 +241,7 @@ fun CommunalHub(
            initialValue = !viewModel.isEditMode
        )

    val contentPadding = gridContentPadding(viewModel.isEditMode, toolbarSize)
    val contentOffset = beforeContentPadding(contentPadding).toOffset()

    val minContentPadding = gridContentPadding(viewModel.isEditMode, toolbarSize)
    ObserveScrollEffect(gridState, viewModel)

    val context = LocalContext.current
@@ -368,7 +367,7 @@ fun CommunalHub(
    ) {
        AccessibilityContainer(viewModel) {
            if (!viewModel.isEditMode && isEmptyState) {
                EmptyStateCta(contentPadding = contentPadding, viewModel = viewModel)
                EmptyStateCta(contentPadding = minContentPadding, viewModel = viewModel)
            } else {
                val slideOffsetInPx =
                    with(LocalDensity.current) { Dimensions.SlideOffsetY.toPx().toInt() }
@@ -397,10 +396,11 @@ fun CommunalHub(
                        CommunalHubLazyGrid(
                            communalContent = communalContent,
                            viewModel = viewModel,
                            contentPadding = contentPadding,
                            minContentPadding = minContentPadding,
                            contentOffset = contentOffset,
                            screenWidth = screenWidth,
                            setGridCoordinates = { gridCoordinates = it },
                            setContentOffset = { contentOffset = it },
                            updateDragPositionForRemove = { boundingBox ->
                                val gridOffset = gridCoordinates?.positionInWindow()
                                val removeButtonCenter =
@@ -742,8 +742,9 @@ fun calculateWidgetSize(

@Composable
private fun HorizontalGridWrapper(
    contentPadding: PaddingValues,
    minContentPadding: PaddingValues,
    gridState: LazyGridState,
    setContentOffset: (offset: Offset) -> Unit,
    modifier: Modifier = Modifier,
    content: LazyGridScope.(sizeInfo: SizeInfo?) -> Unit,
) {
@@ -752,17 +753,26 @@ private fun HorizontalGridWrapper(
            cellAspectRatio = 1.5f,
            modifier = modifier,
            state = gridState,
            minContentPadding = contentPadding,
            minContentPadding = minContentPadding,
            minHorizontalArrangement = Dimensions.ItemSpacing,
            minVerticalArrangement = Dimensions.ItemSpacing,
            setContentOffset = setContentOffset,
            content = content,
        )
    } else {
        val layoutDirection = LocalLayoutDirection.current
        val density = LocalDensity.current

        val minStartPadding = minContentPadding.calculateStartPadding(layoutDirection)
        val minTopPadding = minContentPadding.calculateTopPadding()

        with(density) { setContentOffset(Offset(minStartPadding.toPx(), minTopPadding.toPx())) }

        LazyHorizontalGrid(
            modifier = modifier,
            state = gridState,
            rows = GridCells.Fixed(CommunalContentSize.FixedSize.FULL.span),
            contentPadding = contentPadding,
            contentPadding = minContentPadding,
            horizontalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
            verticalArrangement = Arrangement.spacedBy(Dimensions.ItemSpacing),
        ) {
@@ -776,13 +786,14 @@ private fun HorizontalGridWrapper(
private fun BoxScope.CommunalHubLazyGrid(
    communalContent: List<CommunalContentModel>,
    viewModel: BaseCommunalViewModel,
    contentPadding: PaddingValues,
    minContentPadding: PaddingValues,
    selectedKey: State<String?>,
    screenWidth: Int,
    contentOffset: Offset,
    gridState: LazyGridState,
    contentListState: ContentListState,
    setGridCoordinates: (coordinates: LayoutCoordinates) -> Unit,
    setContentOffset: (offset: Offset) -> Unit,
    updateDragPositionForRemove: (boundingBox: IntRect) -> Boolean,
    widgetConfigurator: WidgetConfigurator?,
    interactionHandler: RemoteViews.InteractionHandler?,
@@ -833,7 +844,8 @@ private fun BoxScope.CommunalHubLazyGrid(
    HorizontalGridWrapper(
        modifier = gridModifier,
        gridState = gridState,
        contentPadding = contentPadding,
        minContentPadding = minContentPadding,
        setContentOffset = setContentOffset,
    ) { sizeInfo ->
        /** Override spans based on the responsive grid size */
        val finalizedList =
@@ -892,7 +904,7 @@ private fun BoxScope.CommunalHubLazyGrid(
                    key = item.key,
                    currentSpan = GridItemSpan(currentItemSpan),
                    gridState = gridState,
                    gridContentPadding = contentPadding,
                    gridContentPadding = sizeInfo?.contentPadding ?: minContentPadding,
                    verticalArrangement =
                        Arrangement.spacedBy(
                            sizeInfo?.verticalArrangement ?: Dimensions.ItemSpacing
@@ -1733,26 +1745,24 @@ private fun gridContentPadding(isEditMode: Boolean, toolbarSize: IntSize?): Padd
    val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
    val screenHeight = with(density) { windowMetrics.bounds.height().toDp() }
    val toolbarHeight = with(density) { Dimensions.ToolbarPaddingTop + toolbarSize.height.toDp() }
    return if (communalResponsiveGrid()) {
        PaddingValues(
            start = Dimensions.ToolbarPaddingHorizontal,
            end = Dimensions.ToolbarPaddingHorizontal,
            top = hubDimensions.GridTopSpacing,
        )
    } else {
        val verticalPadding =
        ((screenHeight - toolbarHeight - hubDimensions.GridHeight + hubDimensions.GridTopSpacing) /
                2)
            ((screenHeight - toolbarHeight - hubDimensions.GridHeight +
                    hubDimensions.GridTopSpacing) / 2)
                .coerceAtLeast(Dimensions.Spacing)
    return PaddingValues(
        PaddingValues(
            start = Dimensions.ToolbarPaddingHorizontal,
            end = Dimensions.ToolbarPaddingHorizontal,
            top = verticalPadding + toolbarHeight,
            bottom = verticalPadding,
        )
    }

@Composable
private fun beforeContentPadding(paddingValues: PaddingValues): ContentPaddingInPx {
    return with(LocalDensity.current) {
        ContentPaddingInPx(
            start = paddingValues.calculateStartPadding(LocalLayoutDirection.current).toPx(),
            top = paddingValues.calculateTopPadding().toPx(),
        )
    }
}

private fun CommunalContentSize.FixedSize.dp(): Dp {
@@ -1770,10 +1780,6 @@ private fun firstIndexAtOffset(gridState: LazyGridState, offset: Offset): Int? =
private fun keyAtIndexIfEditable(list: List<CommunalContentModel>, index: Int): String? =
    if (index in list.indices && list[index].isWidgetContent()) list[index].key else null

data class ContentPaddingInPx(val start: Float, val top: Float) {
    fun toOffset(): Offset = Offset(start, top)
}

class Dimensions(val context: Context, val config: Configuration) {
    val GridTopSpacing: Dp
        get() {
+13 −3
Original line number Diff line number Diff line
@@ -35,7 +35,9 @@ import androidx.compose.foundation.rememberOverscrollEffect
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
@@ -54,6 +56,7 @@ fun ResponsiveLazyHorizontalGrid(
    cellAspectRatio: Float,
    modifier: Modifier = Modifier,
    state: LazyGridState = rememberLazyGridState(),
    setContentOffset: (offset: Offset) -> Unit = {},
    minContentPadding: PaddingValues = PaddingValues(0.dp),
    minHorizontalArrangement: Dp = 0.dp,
    minVerticalArrangement: Dp = 0.dp,
@@ -70,6 +73,7 @@ fun ResponsiveLazyHorizontalGrid(
    BoxWithConstraints(modifier) {
        val gridSize = rememberGridSize(maxWidth = maxWidth, maxHeight = maxHeight)
        val layoutDirection = LocalLayoutDirection.current
        val density = LocalDensity.current

        val minStartPadding = minContentPadding.calculateStartPadding(layoutDirection)
        val minEndPadding = minContentPadding.calculateEndPadding(layoutDirection)
@@ -124,14 +128,19 @@ fun ResponsiveLazyHorizontalGrid(
        val extraWidth = maxWidth - usedWidth
        val extraHeight = maxHeight - usedHeight

        val finalStartPadding = minStartPadding + extraWidth / 2
        val finalTopPadding = minTopPadding + extraHeight / 2

        val finalContentPadding =
            PaddingValues(
                start = minStartPadding + extraWidth / 2,
                start = finalStartPadding,
                end = minEndPadding + extraWidth / 2,
                top = minTopPadding + extraHeight / 2,
                top = finalTopPadding,
                bottom = minBottomPadding + extraHeight / 2,
            )

        with(density) { setContentOffset(Offset(finalStartPadding.toPx(), finalTopPadding.toPx())) }

        LazyHorizontalGrid(
            rows = GridCells.Fixed(gridSize.height),
            modifier = Modifier.fillMaxSize(),
@@ -179,12 +188,13 @@ private fun calculateClosestSize(maxWidth: Dp, maxHeight: Dp, aspectRatio: Float
 * @property verticalArrangement The space between rows in the grid.
 * @property gridSize The size of the grid, in cell units.
 * @property availableHeight The maximum height an item in the grid may occupy.
 * @property contentPadding The padding around the content of the grid.
 */
data class SizeInfo(
    val cellSize: DpSize,
    val verticalArrangement: Dp,
    val gridSize: IntSize,
    private val contentPadding: PaddingValues,
    val contentPadding: PaddingValues,
    private val maxHeight: Dp,
) {
    val availableHeight: Dp