Loading packages/SystemUI/res/values/dimens.xml +1 −0 Original line number Diff line number Diff line Loading @@ -2267,6 +2267,7 @@ <dimen name="tile_details_entry_gap">2dp</dimen> <dimen name="tile_details_bottom_padding">14dp</dimen> <dimen name="tile_details_horizontal_padding">14dp</dimen> <dimen name="tile_details_vertical_padding">8dp</dimen> <!-- Tile Details end --> </resources> packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsContent.kt +13 −1 Original line number Diff line number Diff line Loading @@ -16,11 +16,23 @@ package com.android.systemui.qs.tiles.dialog import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.dimensionResource import com.android.systemui.res.R import com.android.systemui.statusbar.policy.ui.dialog.composable.ModeTileGrid @Composable fun ModesDetailsContent(viewModel: ModesDetailsViewModel) { // TODO(b/378513940): Finish implementing this function. ModeTileGrid(viewModel = viewModel.viewModel) ModeTileGrid( viewModel = viewModel.viewModel, modifier = Modifier.padding( horizontal = dimensionResource(R.dimen.tile_details_horizontal_padding), vertical = dimensionResource(R.dimen.tile_details_vertical_padding), ), inDetailsView = true, ) } packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt +45 −6 Original line number Diff line number Diff line Loading @@ -45,21 +45,42 @@ import androidx.compose.ui.unit.dp import com.android.systemui.common.ui.compose.Icon import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModeTileViewModel enum class ModeTileType { // The standard tile type. Will be used when the tile is shown in a dialog. DEFAULT, // Special types used for the details view. START_TILE, MIDDLE_TILE, END_TILE, ONLY_TILE, } @Composable fun ModeTile(viewModel: ModeTileViewModel, modifier: Modifier = Modifier) { fun ModeTile( viewModel: ModeTileViewModel, modifier: Modifier = Modifier, type: ModeTileType = ModeTileType.DEFAULT, ) { val tileColor: Color by animateColorAsState( if (viewModel.enabled) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant when { viewModel.enabled -> MaterialTheme.colorScheme.primary type == ModeTileType.DEFAULT -> MaterialTheme.colorScheme.surfaceVariant else -> MaterialTheme.colorScheme.primaryContainer } ) val contentColor: Color by animateColorAsState( if (viewModel.enabled) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurfaceVariant when { viewModel.enabled -> MaterialTheme.colorScheme.onPrimary type == ModeTileType.DEFAULT -> MaterialTheme.colorScheme.onSurfaceVariant else -> MaterialTheme.colorScheme.onSurface } ) CompositionLocalProvider(LocalContentColor provides contentColor) { Surface(color = tileColor, shape = RoundedCornerShape(16.dp), modifier = modifier) { Surface(color = tileColor, shape = TileShape.getTileShape(type), modifier = modifier) { Row( modifier = Modifier.combinedClickable( Loading Loading @@ -99,3 +120,21 @@ fun ModeTile(viewModel: ModeTileViewModel, modifier: Modifier = Modifier) { private fun Modifier.tileMarquee(): Modifier { return this.basicMarquee(iterations = 1) } private object TileShape { const val DEFAULT_RADIUS = 16 const val LARGE_RADIUS = 28 const val NO_RADIUS = 0 fun getTileShape(type: ModeTileType): RoundedCornerShape { return when (type) { ModeTileType.DEFAULT -> RoundedCornerShape(DEFAULT_RADIUS.dp) ModeTileType.START_TILE -> RoundedCornerShape(topStart = LARGE_RADIUS.dp, topEnd = LARGE_RADIUS.dp) ModeTileType.MIDDLE_TILE -> RoundedCornerShape(NO_RADIUS) ModeTileType.END_TILE -> RoundedCornerShape(bottomStart = LARGE_RADIUS.dp, bottomEnd = LARGE_RADIUS.dp) ModeTileType.ONLY_TILE -> RoundedCornerShape(LARGE_RADIUS) } } } packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt +35 −7 Original line number Diff line number Diff line Loading @@ -38,9 +38,15 @@ import com.android.systemui.common.ui.compose.PagerDots import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel @Composable fun ModeTileGrid(viewModel: ModesDialogViewModel) { fun ModeTileGrid( viewModel: ModesDialogViewModel, modifier: Modifier = Modifier, inDetailsView: Boolean = false, ) { val tiles by viewModel.tiles.collectAsStateWithLifecycle(initialValue = emptyList()) val verticalSpacing = if (inDetailsView) 2.dp else 8.dp if (Flags.modesUiDialogPaging()) { val tilesPerPage = 3 val totalPages = { (tiles.size + tilesPerPage - 1) / tilesPerPage } Loading @@ -49,7 +55,7 @@ fun ModeTileGrid(viewModel: ModesDialogViewModel) { Column { HorizontalPager( state = pagerState, modifier = Modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(), pageSpacing = 16.dp, verticalAlignment = Alignment.Top, // Pre-emptively layout and compose the next page, to make sure the height stays Loading @@ -58,12 +64,17 @@ fun ModeTileGrid(viewModel: ModesDialogViewModel) { ) { page -> Column( modifier = Modifier.fillMaxWidth().fillMaxHeight(), verticalArrangement = Arrangement.spacedBy(8.dp, alignment = Alignment.Top), verticalArrangement = Arrangement.spacedBy(verticalSpacing, alignment = Alignment.Top), ) { val startIndex = page * tilesPerPage val endIndex = minOf((page + 1) * tilesPerPage, tiles.size) for (index in startIndex until endIndex) { ModeTile(viewModel = tiles[index], modifier = Modifier.fillMaxWidth()) ModeTile( viewModel = tiles[index], modifier = Modifier.fillMaxWidth(), type = getModeTileType(inDetailsView, index, tiles.size), ) } } } Loading @@ -78,13 +89,30 @@ fun ModeTileGrid(viewModel: ModesDialogViewModel) { } else { LazyVerticalGrid( columns = GridCells.Fixed(1), modifier = Modifier.fillMaxWidth().heightIn(max = 280.dp), verticalArrangement = Arrangement.spacedBy(8.dp), modifier = modifier.fillMaxWidth().heightIn(max = 280.dp), verticalArrangement = Arrangement.spacedBy(verticalSpacing), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { items(tiles.size, key = { index -> tiles[index].id }) { index -> ModeTile(viewModel = tiles[index]) ModeTile( viewModel = tiles[index], type = getModeTileType(inDetailsView, index, tiles.size), ) } } } } fun getModeTileType(inDetailsView: Boolean, index: Int, tilesSize: Int): ModeTileType { return if (inDetailsView) { if (tilesSize == 1) return ModeTileType.ONLY_TILE when (index) { 0 -> ModeTileType.START_TILE tilesSize - 1 -> ModeTileType.END_TILE else -> ModeTileType.MIDDLE_TILE } } else { ModeTileType.DEFAULT } } Loading
packages/SystemUI/res/values/dimens.xml +1 −0 Original line number Diff line number Diff line Loading @@ -2267,6 +2267,7 @@ <dimen name="tile_details_entry_gap">2dp</dimen> <dimen name="tile_details_bottom_padding">14dp</dimen> <dimen name="tile_details_horizontal_padding">14dp</dimen> <dimen name="tile_details_vertical_padding">8dp</dimen> <!-- Tile Details end --> </resources>
packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ModesDetailsContent.kt +13 −1 Original line number Diff line number Diff line Loading @@ -16,11 +16,23 @@ package com.android.systemui.qs.tiles.dialog import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.dimensionResource import com.android.systemui.res.R import com.android.systemui.statusbar.policy.ui.dialog.composable.ModeTileGrid @Composable fun ModesDetailsContent(viewModel: ModesDetailsViewModel) { // TODO(b/378513940): Finish implementing this function. ModeTileGrid(viewModel = viewModel.viewModel) ModeTileGrid( viewModel = viewModel.viewModel, modifier = Modifier.padding( horizontal = dimensionResource(R.dimen.tile_details_horizontal_padding), vertical = dimensionResource(R.dimen.tile_details_vertical_padding), ), inDetailsView = true, ) }
packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt +45 −6 Original line number Diff line number Diff line Loading @@ -45,21 +45,42 @@ import androidx.compose.ui.unit.dp import com.android.systemui.common.ui.compose.Icon import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModeTileViewModel enum class ModeTileType { // The standard tile type. Will be used when the tile is shown in a dialog. DEFAULT, // Special types used for the details view. START_TILE, MIDDLE_TILE, END_TILE, ONLY_TILE, } @Composable fun ModeTile(viewModel: ModeTileViewModel, modifier: Modifier = Modifier) { fun ModeTile( viewModel: ModeTileViewModel, modifier: Modifier = Modifier, type: ModeTileType = ModeTileType.DEFAULT, ) { val tileColor: Color by animateColorAsState( if (viewModel.enabled) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceVariant when { viewModel.enabled -> MaterialTheme.colorScheme.primary type == ModeTileType.DEFAULT -> MaterialTheme.colorScheme.surfaceVariant else -> MaterialTheme.colorScheme.primaryContainer } ) val contentColor: Color by animateColorAsState( if (viewModel.enabled) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurfaceVariant when { viewModel.enabled -> MaterialTheme.colorScheme.onPrimary type == ModeTileType.DEFAULT -> MaterialTheme.colorScheme.onSurfaceVariant else -> MaterialTheme.colorScheme.onSurface } ) CompositionLocalProvider(LocalContentColor provides contentColor) { Surface(color = tileColor, shape = RoundedCornerShape(16.dp), modifier = modifier) { Surface(color = tileColor, shape = TileShape.getTileShape(type), modifier = modifier) { Row( modifier = Modifier.combinedClickable( Loading Loading @@ -99,3 +120,21 @@ fun ModeTile(viewModel: ModeTileViewModel, modifier: Modifier = Modifier) { private fun Modifier.tileMarquee(): Modifier { return this.basicMarquee(iterations = 1) } private object TileShape { const val DEFAULT_RADIUS = 16 const val LARGE_RADIUS = 28 const val NO_RADIUS = 0 fun getTileShape(type: ModeTileType): RoundedCornerShape { return when (type) { ModeTileType.DEFAULT -> RoundedCornerShape(DEFAULT_RADIUS.dp) ModeTileType.START_TILE -> RoundedCornerShape(topStart = LARGE_RADIUS.dp, topEnd = LARGE_RADIUS.dp) ModeTileType.MIDDLE_TILE -> RoundedCornerShape(NO_RADIUS) ModeTileType.END_TILE -> RoundedCornerShape(bottomStart = LARGE_RADIUS.dp, bottomEnd = LARGE_RADIUS.dp) ModeTileType.ONLY_TILE -> RoundedCornerShape(LARGE_RADIUS) } } }
packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTileGrid.kt +35 −7 Original line number Diff line number Diff line Loading @@ -38,9 +38,15 @@ import com.android.systemui.common.ui.compose.PagerDots import com.android.systemui.statusbar.policy.ui.dialog.viewmodel.ModesDialogViewModel @Composable fun ModeTileGrid(viewModel: ModesDialogViewModel) { fun ModeTileGrid( viewModel: ModesDialogViewModel, modifier: Modifier = Modifier, inDetailsView: Boolean = false, ) { val tiles by viewModel.tiles.collectAsStateWithLifecycle(initialValue = emptyList()) val verticalSpacing = if (inDetailsView) 2.dp else 8.dp if (Flags.modesUiDialogPaging()) { val tilesPerPage = 3 val totalPages = { (tiles.size + tilesPerPage - 1) / tilesPerPage } Loading @@ -49,7 +55,7 @@ fun ModeTileGrid(viewModel: ModesDialogViewModel) { Column { HorizontalPager( state = pagerState, modifier = Modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(), pageSpacing = 16.dp, verticalAlignment = Alignment.Top, // Pre-emptively layout and compose the next page, to make sure the height stays Loading @@ -58,12 +64,17 @@ fun ModeTileGrid(viewModel: ModesDialogViewModel) { ) { page -> Column( modifier = Modifier.fillMaxWidth().fillMaxHeight(), verticalArrangement = Arrangement.spacedBy(8.dp, alignment = Alignment.Top), verticalArrangement = Arrangement.spacedBy(verticalSpacing, alignment = Alignment.Top), ) { val startIndex = page * tilesPerPage val endIndex = minOf((page + 1) * tilesPerPage, tiles.size) for (index in startIndex until endIndex) { ModeTile(viewModel = tiles[index], modifier = Modifier.fillMaxWidth()) ModeTile( viewModel = tiles[index], modifier = Modifier.fillMaxWidth(), type = getModeTileType(inDetailsView, index, tiles.size), ) } } } Loading @@ -78,13 +89,30 @@ fun ModeTileGrid(viewModel: ModesDialogViewModel) { } else { LazyVerticalGrid( columns = GridCells.Fixed(1), modifier = Modifier.fillMaxWidth().heightIn(max = 280.dp), verticalArrangement = Arrangement.spacedBy(8.dp), modifier = modifier.fillMaxWidth().heightIn(max = 280.dp), verticalArrangement = Arrangement.spacedBy(verticalSpacing), horizontalArrangement = Arrangement.spacedBy(8.dp), ) { items(tiles.size, key = { index -> tiles[index].id }) { index -> ModeTile(viewModel = tiles[index]) ModeTile( viewModel = tiles[index], type = getModeTileType(inDetailsView, index, tiles.size), ) } } } } fun getModeTileType(inDetailsView: Boolean, index: Int, tilesSize: Int): ModeTileType { return if (inDetailsView) { if (tilesSize == 1) return ModeTileType.ONLY_TILE when (index) { 0 -> ModeTileType.START_TILE tilesSize - 1 -> ModeTileType.END_TILE else -> ModeTileType.MIDDLE_TILE } } else { ModeTileType.DEFAULT } }