diff options
| author | 2023-10-27 08:16:08 -0700 | |
|---|---|---|
| committer | 2023-10-30 17:27:24 -0700 | |
| commit | b8a2ee16f070f4a4642833adb4811287b731dca7 (patch) | |
| tree | 94027f5c81aad0d4fc532cde9b981ace046e7946 | |
| parent | e619e972988d960bad876ded08ec1d222fb740da (diff) | |
Reimplement CommunalHub with LazyHorizontalGrid
This change strips out dependency on the CommunalLayoutLib, and
reimplements the UI layer with LazyHorizontalGrid. Now the Compose UI
layer simply renders cards at the given size in the given order. It's up
to upstream layers to decide the sizes and ordering.
Test: verified that CommunalHub renders all three sizes correctly, and
there is no visual delta
Test: veriified that as cards are added / removed, existing cards
maintain state
Bug: 307942173
Fix: 307942173
Flag: ACONFIG com.android.systemui.communal_hub DEVELOPMENT
Change-Id: Ie807b1f1c2e776156ce2c402f372a5bf55064655
5 files changed, 105 insertions, 77 deletions
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp index 17cc9f8135f4..f78811f5bb14 100644 --- a/packages/SystemUI/Android.bp +++ b/packages/SystemUI/Android.bp @@ -60,7 +60,6 @@ systemui_compose_java_defaults { // except for SystemUI-core. // Copied from compose/features/Android.bp. static_libs: [ - "CommunalLayoutLib", "PlatformComposeCore", "PlatformComposeSceneTransitionLayout", 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 b8fb26406801..87a8c35388fa 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 @@ -4,8 +4,14 @@ import android.appwidget.AppWidgetHostView import android.os.Bundle import android.util.SizeF import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.GridItemSpan +import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid import androidx.compose.material3.Card import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -13,16 +19,12 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.dimensionResource -import androidx.compose.ui.res.integerResource +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView -import com.android.systemui.communal.layout.ui.compose.CommunalGridLayout -import com.android.systemui.communal.layout.ui.compose.config.CommunalGridLayoutCard -import com.android.systemui.communal.layout.ui.compose.config.CommunalGridLayoutConfig import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.ui.model.CommunalContentUiModel import com.android.systemui.communal.ui.viewmodel.CommunalViewModel -import com.android.systemui.res.R @Composable fun CommunalHub( @@ -34,68 +36,91 @@ fun CommunalHub( Box( modifier = modifier.fillMaxSize().background(Color.White), ) { - CommunalGridLayout( - modifier = Modifier.align(Alignment.CenterStart), - layoutConfig = - CommunalGridLayoutConfig( - gridColumnSize = dimensionResource(R.dimen.communal_grid_column_size), - gridGutter = dimensionResource(R.dimen.communal_grid_gutter_size), - gridHeight = dimensionResource(R.dimen.communal_grid_height), - gridColumnsPerCard = integerResource(R.integer.communal_grid_columns_per_card), - ), - communalCards = if (showTutorial) tutorialContent else widgetContent.map(::contentCard), - ) + LazyHorizontalGrid( + modifier = modifier.height(Dimensions.GridHeight).align(Alignment.CenterStart), + rows = GridCells.Fixed(CommunalContentSize.FULL.span), + horizontalArrangement = Arrangement.spacedBy(Dimensions.Spacing), + verticalArrangement = Arrangement.spacedBy(Dimensions.Spacing), + ) { + if (showTutorial) { + items( + count = tutorialContentSizes.size, + // TODO(b/308148193): a more scalable solution for unique ids. + key = { index -> "tutorial_$index" }, + span = { index -> GridItemSpan(tutorialContentSizes[index].span) }, + ) { index -> + TutorialCard( + modifier = + Modifier.size(Dimensions.CardWidth, tutorialContentSizes[index].dp()), + ) + } + } else { + items( + count = widgetContent.size, + key = { index -> widgetContent[index].id }, + span = { index -> GridItemSpan(widgetContent[index].size.span) }, + ) { index -> + val widget = widgetContent[index] + ContentCard( + modifier = Modifier.size(Dimensions.CardWidth, widget.size.dp()), + model = widget, + ) + } + } + } } } -private val tutorialContent = - listOf( - tutorialCard(CommunalGridLayoutCard.Size.FULL), - tutorialCard(CommunalGridLayoutCard.Size.THIRD), - tutorialCard(CommunalGridLayoutCard.Size.THIRD), - tutorialCard(CommunalGridLayoutCard.Size.THIRD), - tutorialCard(CommunalGridLayoutCard.Size.HALF), - tutorialCard(CommunalGridLayoutCard.Size.HALF), - tutorialCard(CommunalGridLayoutCard.Size.HALF), - tutorialCard(CommunalGridLayoutCard.Size.HALF), - ) - -private fun tutorialCard(size: CommunalGridLayoutCard.Size): CommunalGridLayoutCard { - return object : CommunalGridLayoutCard() { - override val supportedSizes = listOf(size) - - @Composable - override fun Content(modifier: Modifier, size: SizeF) { - Card(modifier = modifier, content = {}) - } - } +// A placeholder for tutorial content. +@Composable +private fun TutorialCard(modifier: Modifier = Modifier) { + Card(modifier = modifier, content = {}) } -private fun contentCard(model: CommunalContentUiModel): CommunalGridLayoutCard { - return object : CommunalGridLayoutCard() { - override val supportedSizes = listOf(convertToCardSize(model.size)) - override val priority = model.priority +@Composable +private fun ContentCard( + model: CommunalContentUiModel, + modifier: Modifier = Modifier, +) { + AndroidView( + modifier = modifier, + factory = { + model.view.apply { + if (this is AppWidgetHostView) { + val size = SizeF(Dimensions.CardWidth.value, model.size.dp().value) + updateAppWidgetSize(Bundle.EMPTY, listOf(size)) + } + } + }, + ) +} - @Composable - override fun Content(modifier: Modifier, size: SizeF) { - AndroidView( - modifier = modifier, - factory = { - model.view.apply { - if (this is AppWidgetHostView) { - updateAppWidgetSize(Bundle(), listOf(size)) - } - } - }, - ) - } +private fun CommunalContentSize.dp(): Dp { + return when (this) { + CommunalContentSize.FULL -> Dimensions.CardHeightFull + CommunalContentSize.HALF -> Dimensions.CardHeightHalf + CommunalContentSize.THIRD -> Dimensions.CardHeightThird } } -private fun convertToCardSize(size: CommunalContentSize): CommunalGridLayoutCard.Size { - return when (size) { - CommunalContentSize.FULL -> CommunalGridLayoutCard.Size.FULL - CommunalContentSize.HALF -> CommunalGridLayoutCard.Size.HALF - CommunalContentSize.THIRD -> CommunalGridLayoutCard.Size.THIRD - } +// Sizes for the tutorial placeholders. +private val tutorialContentSizes = + listOf( + CommunalContentSize.FULL, + CommunalContentSize.THIRD, + CommunalContentSize.THIRD, + CommunalContentSize.THIRD, + CommunalContentSize.HALF, + CommunalContentSize.HALF, + CommunalContentSize.HALF, + CommunalContentSize.HALF, + ) + +private object Dimensions { + val CardWidth = 464.dp + val CardHeightFull = 630.dp + val CardHeightHalf = 307.dp + val CardHeightThird = 199.dp + val GridHeight = CardHeightFull + val Spacing = 16.dp } diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalContentSize.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalContentSize.kt index 39a6476929ed..c903709aa2ee 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalContentSize.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalContentSize.kt @@ -16,14 +16,19 @@ package com.android.systemui.communal.shared.model -/** Supported sizes for communal content in the layout grid. */ -enum class CommunalContentSize { +/** + * Supported sizes for communal content in the layout grid. + * + * @param span The span of the content in a column. For example, if FULL is 6, then 3 represents + * HALF, 2 represents THIRD, and 1 represents SIXTH. + */ +enum class CommunalContentSize(val span: Int) { /** Content takes the full height of the column. */ - FULL, + FULL(6), /** Content takes half of the height of the column. */ - HALF, + HALF(3), /** Content takes a third of the height of the column. */ - THIRD, + THIRD(2), } diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/model/CommunalContentUiModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/model/CommunalContentUiModel.kt index 98060dc1dceb..b60dc2a21699 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/model/CommunalContentUiModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/model/CommunalContentUiModel.kt @@ -9,7 +9,7 @@ import com.android.systemui.communal.shared.model.CommunalContentSize * This model stays in the UI layer. */ data class CommunalContentUiModel( + val id: String, val view: View, - val size: CommunalContentSize, - val priority: Int, + val size: CommunalContentSize = CommunalContentSize.HALF, ) diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt index 25c64eafe255..390b580bad28 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt @@ -20,7 +20,6 @@ import android.appwidget.AppWidgetHost import android.content.Context import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor -import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.ui.model.CommunalContentUiModel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application @@ -42,16 +41,16 @@ constructor( /** List of widgets to be displayed in the communal hub. */ val widgetContent: Flow<List<CommunalContentUiModel>> = - communalInteractor.widgetContent.map { - it.map { + communalInteractor.widgetContent.map { widgets -> + widgets.map Widget@{ widget -> // TODO(b/306406256): As adding and removing widgets functionalities are // supported, cache the host views so they're not recreated each time. - val hostView = appWidgetHost.createView(context, it.appWidgetId, it.providerInfo) - return@map CommunalContentUiModel( + val hostView = + appWidgetHost.createView(context, widget.appWidgetId, widget.providerInfo) + return@Widget CommunalContentUiModel( + // TODO(b/308148193): a more scalable solution for unique ids. + id = "widget_${widget.appWidgetId}", view = hostView, - priority = it.priority, - // All widgets have HALF size. - size = CommunalContentSize.HALF, ) } } |