Loading packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt +17 −49 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.systemui.qs.composefragment import android.annotation.SuppressLint import android.content.Context import android.content.res.Configuration import android.graphics.PointF import android.graphics.Rect import android.os.Bundle Loading Loading @@ -49,7 +48,6 @@ import androidx.compose.foundation.layout.requiredHeightIn import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue Loading @@ -72,8 +70,6 @@ import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInRoot import androidx.compose.ui.layout.positionOnScreen import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.CustomAccessibilityAction Loading Loading @@ -255,7 +251,7 @@ constructor( @Composable private fun Content() { PlatformTheme(isDarkTheme = true /* Delete AlwaysDarkMode when removing this */) { PlatformTheme { ProvideShortcutHelperIndication(interactionsConfig = interactionsConfig()) { // TODO(b/389985793): Make sure that there is no coroutine work or recompositions // happening when alwaysCompose is true but isQsVisibleAndAnyShadeExpanded is false. Loading Loading @@ -747,7 +743,6 @@ constructor( ) val BrightnessSlider = @Composable { AlwaysDarkMode { Box( Modifier.systemGestureExclusionInShade( enabled = { Loading @@ -756,8 +751,7 @@ constructor( ) ) { BrightnessSliderContainer( viewModel = containerViewModel.brightnessSliderViewModel, viewModel = containerViewModel.brightnessSliderViewModel, containerColors = ContainerColors( Color.Transparent, Loading @@ -767,7 +761,6 @@ constructor( ) } } } val TileGrid = @Composable { Box { Loading Loading @@ -1243,28 +1236,3 @@ private fun interactionsConfig() = private inline val alwaysCompose get() = Flags.alwaysComposeQsUiFragment() /** * Forces the configuration and themes to be dark theme. This is needed in order to have * [colorResource] retrieve the dark mode colors. * * This should be removed when we remove the force dark mode in [PlatformTheme] at the root of the * compose hierarchy. */ @Composable private fun AlwaysDarkMode(content: @Composable () -> Unit) { val currentConfig = LocalConfiguration.current val darkConfig = Configuration(currentConfig).apply { uiMode = (uiMode and (Configuration.UI_MODE_NIGHT_MASK.inv())) or Configuration.UI_MODE_NIGHT_YES } val newContext = LocalContext.current.createConfigurationContext(darkConfig) CompositionLocalProvider( LocalConfiguration provides darkConfig, LocalContext provides newContext, ) { content() } } packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt +85 −45 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Clear import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton Loading @@ -89,6 +90,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.CornerRadius import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.isSpecified import androidx.compose.ui.graphics.Color Loading @@ -115,6 +117,7 @@ import androidx.compose.ui.unit.sp import androidx.compose.ui.util.fastMap import com.android.compose.gesture.effect.rememberOffsetOverscrollEffectFactory import com.android.compose.modifiers.height import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.common.ui.compose.load import com.android.systemui.qs.panels.shared.model.SizedTile import com.android.systemui.qs.panels.shared.model.SizedTileImpl Loading @@ -132,6 +135,7 @@ import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaul import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.AUTO_SCROLL_SPEED import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.AvailableTilesGridMinHeight import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.CurrentTilesGridPadding import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.GridBackgroundCornerRadius import com.android.systemui.qs.panels.ui.compose.selection.InteractiveTileContainer import com.android.systemui.qs.panels.ui.compose.selection.MutableSelectionState import com.android.systemui.qs.panels.ui.compose.selection.ResizingState Loading Loading @@ -164,14 +168,27 @@ object TileType @OptIn(ExperimentalMaterial3Api::class) @Composable private fun EditModeTopBar(onStopEditing: () -> Unit, onReset: (() -> Unit)?) { val primaryContainerColor = MaterialTheme.colorScheme.primaryContainer TopAppBar( colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent), title = { Text(text = stringResource(id = R.string.qs_edit)) }, colors = TopAppBarDefaults.topAppBarColors( containerColor = Color.Transparent, titleContentColor = MaterialTheme.colorScheme.onSurface, ), title = { Text( text = stringResource(id = R.string.qs_edit), modifier = Modifier.padding(start = 24.dp), ) }, navigationIcon = { IconButton(onClick = onStopEditing) { IconButton( onClick = onStopEditing, modifier = Modifier.drawBehind { drawCircle(primaryContainerColor) }, ) { Icon( Icons.AutoMirrored.Filled.ArrowBack, tint = MaterialTheme.colorScheme.onSurface, contentDescription = stringResource(id = com.android.internal.R.string.action_bar_up_description), ) Loading @@ -179,11 +196,19 @@ private fun EditModeTopBar(onStopEditing: () -> Unit, onReset: (() -> Unit)?) { }, actions = { if (onReset != null) { TextButton(onClick = onReset) { TextButton( onClick = onReset, colors = ButtonDefaults.textButtonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ), ) { Text(stringResource(id = com.android.internal.R.string.reset)) } } }, modifier = Modifier.padding(vertical = 8.dp), ) } Loading Loading @@ -247,7 +272,7 @@ fun DefaultEditTileGrid( targetState = listState.dragInProgress || selectionState.selected, label = "QSEditHeader", contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth().heightIn(min = 80.dp), modifier = Modifier.fillMaxWidth().heightIn(min = 48.dp), ) { showRemoveTarget -> EditGridHeader { if (showRemoveTarget) { Loading Loading @@ -292,10 +317,6 @@ fun DefaultEditTileGrid( spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin)), modifier = modifier.fillMaxSize(), ) { EditGridHeader { Text(text = stringResource(id = R.string.drag_to_add_tiles)) } val availableTiles = remember { mutableStateListOf<AvailableTileGridCell>().apply { addAll(toAvailableTiles(listState.tiles, otherTiles)) Loading Loading @@ -374,9 +395,7 @@ private fun EditGridHeader( modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit, ) { CompositionLocalProvider( LocalContentColor provides MaterialTheme.colorScheme.onBackground.copy(alpha = .5f) ) { CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) { Box(contentAlignment = Alignment.Center, modifier = modifier.fillMaxWidth()) { content() } } } Loading Loading @@ -423,6 +442,7 @@ private fun CurrentTilesGrid( listState.tiles.fastMap { Pair(it, BounceableTileViewModel()) } } val primaryColor = MaterialTheme.colorScheme.primary TileLazyGrid( state = gridState, columns = GridCells.Fixed(columns), Loading @@ -431,9 +451,9 @@ private fun CurrentTilesGrid( Modifier.fillMaxWidth() .height { totalHeight.roundToPx() } .border( width = 1.dp, color = MaterialTheme.colorScheme.onBackground.copy(alpha = .5f), shape = RoundedCornerShape((TileHeight / 2) + CurrentTilesGridPadding), width = 2.dp, color = primaryColor, shape = RoundedCornerShape(GridBackgroundCornerRadius), ) .dragAndDropTileList(gridState, { gridContentOffset }, listState) { spec -> onSetTiles(currentListState.tileSpecs()) Loading @@ -442,6 +462,13 @@ private fun CurrentTilesGrid( .onGloballyPositioned { coordinates -> gridContentOffset = coordinates.positionInRoot() } .drawBehind { drawRoundRect( primaryColor, cornerRadius = CornerRadius(GridBackgroundCornerRadius.toPx()), alpha = .15f, ) } .testTag(CURRENT_TILES_GRID_TEST_TAG), ) { EditTiles(cells, listState, selectionState, coroutineScope, largeTilesSpan, onRemoveTile) { Loading Loading @@ -472,7 +499,6 @@ private fun AvailableTileGrid( remember(tiles.fastMap { it.tile.category }, tiles.fastMap { it.tile.label }) { groupAndSort(tiles) } val labelColors = EditModeTileDefaults.editTileColors() // Available tiles Column( Loading @@ -483,12 +509,24 @@ private fun AvailableTileGrid( ) { groupedTiles.forEach { (category, tiles) -> key(category) { val surfaceColor = MaterialTheme.colorScheme.surface Column( verticalArrangement = spacedBy(16.dp), modifier = Modifier.drawBehind { drawRoundRect( surfaceColor, cornerRadius = CornerRadius(GridBackgroundCornerRadius.toPx()), alpha = .32f, ) } .padding(16.dp), ) { Text( text = category.label.load() ?: "", fontSize = 20.sp, color = labelColors.label, modifier = Modifier.fillMaxWidth().padding(start = 16.dp, bottom = 8.dp, top = 8.dp), color = MaterialTheme.colorScheme.onSurface, modifier = Modifier.fillMaxWidth().padding(start = 8.dp, bottom = 16.dp), ) tiles.chunked(columns).forEach { row -> Row( Loading @@ -515,6 +553,7 @@ private fun AvailableTileGrid( } } } } fun gridHeight(rows: Int, tileHeight: Dp, tilePadding: Dp, gridPadding: Dp): Dp { return ((tileHeight + tilePadding) * rows) + gridPadding * 2 Loading Loading @@ -764,7 +803,7 @@ private fun AvailableTileGridCell( color = colors.label, overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Center, modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.TopCenter), ) } } Loading Loading @@ -864,15 +903,16 @@ private object EditModeTileDefaults { const val AUTO_SCROLL_SPEED = 2 // 2ms per pixel val CurrentTilesGridPadding = 10.dp val AvailableTilesGridMinHeight = 200.dp val GridBackgroundCornerRadius = 42.dp @Composable fun editTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surfaceVariant, iconBackground = MaterialTheme.colorScheme.surfaceVariant, label = MaterialTheme.colorScheme.onSurfaceVariant, secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, icon = MaterialTheme.colorScheme.onSurfaceVariant, background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = Color.Transparent, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onSurface, ) } Loading packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt +26 −18 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.service.quicksettings.Tile.STATE_ACTIVE import android.service.quicksettings.Tile.STATE_INACTIVE import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable Loading Loading @@ -59,6 +60,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.semantics.Role Loading @@ -75,6 +77,7 @@ import com.android.app.tracing.coroutines.launchTraced as launch import com.android.compose.animation.Expandable import com.android.compose.animation.bounceable import com.android.compose.modifiers.thenIf import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.Flags import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon Loading Loading @@ -165,6 +168,7 @@ fun Tile( // TODO(b/361789146): Draw the shapes instead of clipping val tileShape by TileDefaults.animateTileShapeAsState(uiState.state) val animatedColor by animateColorAsState(colors.background, label = "QSTileBackgroundColor") val animatedAlpha by animateFloatAsState(colors.alpha, label = "QSTileAlpha") TileExpandable( color = { animatedColor }, Loading @@ -181,7 +185,8 @@ fun Tile( nextBounceable = currentBounceableInfo.nextTile, orientation = Orientation.Horizontal, bounceEnd = currentBounceableInfo.bounceEnd, ), ) .graphicsLayer { alpha = animatedAlpha }, ) { expandable -> val longClick: (() -> Unit)? = { Loading Loading @@ -370,6 +375,7 @@ data class TileColors( val label: Color, val secondaryLabel: Color, val icon: Color, val alpha: Float = 1f, ) private object TileDefaults { Loading @@ -393,10 +399,10 @@ private object TileDefaults { @ReadOnlyComposable fun activeDualTargetTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surfaceVariant, background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = MaterialTheme.colorScheme.primary, label = MaterialTheme.colorScheme.onSurfaceVariant, secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onPrimary, ) Loading @@ -404,34 +410,36 @@ private object TileDefaults { @ReadOnlyComposable fun inactiveDualTargetTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surfaceVariant, iconBackground = MaterialTheme.colorScheme.surfaceContainerHighest, label = MaterialTheme.colorScheme.onSurfaceVariant, secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, icon = MaterialTheme.colorScheme.onSurfaceVariant, background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = LocalAndroidColorScheme.current.surfaceEffect3, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onSurface, ) @Composable @ReadOnlyComposable fun inactiveTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surfaceVariant, iconBackground = MaterialTheme.colorScheme.surfaceVariant, label = MaterialTheme.colorScheme.onSurfaceVariant, secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, icon = MaterialTheme.colorScheme.onSurfaceVariant, background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = Color.Transparent, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onSurface, ) @Composable @ReadOnlyComposable fun unavailableTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surface, iconBackground = MaterialTheme.colorScheme.surface, fun unavailableTileColors(): TileColors { return TileColors( background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = LocalAndroidColorScheme.current.surfaceEffect2, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onSurface, alpha = .38f, ) } @Composable @ReadOnlyComposable Loading packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt +5 −4 Original line number Diff line number Diff line Loading @@ -62,7 +62,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.toSize import androidx.compose.ui.zIndex import com.android.compose.modifiers.size import com.android.compose.modifiers.thenIf import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.InactiveCornerRadius import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.BADGE_ANGLE_RAD Loading Loading @@ -155,6 +154,7 @@ fun InteractiveTileContainer( Icon( Icons.Default.Remove, contentDescription = null, tint = MaterialTheme.colorScheme.onPrimaryContainer, modifier = Modifier.size(size).align(Alignment.Center).graphicsLayer { this.alpha = badgeIconAlpha Loading Loading @@ -218,14 +218,15 @@ fun StaticTileBadge( ) } ) { val secondaryColor = MaterialTheme.colorScheme.secondary val size = with(LocalDensity.current) { BadgeIconSize.toDp() } val primaryColor = MaterialTheme.colorScheme.primary Icon( icon, contentDescription = contentDescription, tint = MaterialTheme.colorScheme.onPrimary, modifier = Modifier.size(size).align(Alignment.Center).drawBehind { drawCircle(secondaryColor, radius = BadgeSize.toPx() / 2) drawCircle(primaryColor, radius = BadgeSize.toPx() / 2) }, ) } Loading Loading @@ -291,7 +292,7 @@ private fun Transition<TileState>.animateColor(): State<Color> { return animateColor { state -> when (state) { None -> Color.Transparent Removable -> MaterialTheme.colorScheme.secondary Removable -> MaterialTheme.colorScheme.primaryContainer Selected -> MaterialTheme.colorScheme.primary } } Loading packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt +16 −13 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import androidx.compose.ui.text.AnnotatedString import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.FlakyTest import androidx.test.filters.SmallTest import com.android.compose.theme.PlatformTheme import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon Loading @@ -55,6 +56,7 @@ class DragAndDropTest : SysuiTestCase() { listState: EditTileListState, onSetTiles: (List<TileSpec>) -> Unit, ) { PlatformTheme { DefaultEditTileGrid( listState = listState, otherTiles = listOf(), Loading @@ -69,6 +71,7 @@ class DragAndDropTest : SysuiTestCase() { onReset = null, ) } } @Test fun draggedTile_shouldDisappear() { Loading Loading
packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt +17 −49 Original line number Diff line number Diff line Loading @@ -18,7 +18,6 @@ package com.android.systemui.qs.composefragment import android.annotation.SuppressLint import android.content.Context import android.content.res.Configuration import android.graphics.PointF import android.graphics.Rect import android.os.Bundle Loading Loading @@ -49,7 +48,6 @@ import androidx.compose.foundation.layout.requiredHeightIn import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue Loading @@ -72,8 +70,6 @@ import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInRoot import androidx.compose.ui.layout.positionOnScreen import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.CustomAccessibilityAction Loading Loading @@ -255,7 +251,7 @@ constructor( @Composable private fun Content() { PlatformTheme(isDarkTheme = true /* Delete AlwaysDarkMode when removing this */) { PlatformTheme { ProvideShortcutHelperIndication(interactionsConfig = interactionsConfig()) { // TODO(b/389985793): Make sure that there is no coroutine work or recompositions // happening when alwaysCompose is true but isQsVisibleAndAnyShadeExpanded is false. Loading Loading @@ -747,7 +743,6 @@ constructor( ) val BrightnessSlider = @Composable { AlwaysDarkMode { Box( Modifier.systemGestureExclusionInShade( enabled = { Loading @@ -756,8 +751,7 @@ constructor( ) ) { BrightnessSliderContainer( viewModel = containerViewModel.brightnessSliderViewModel, viewModel = containerViewModel.brightnessSliderViewModel, containerColors = ContainerColors( Color.Transparent, Loading @@ -767,7 +761,6 @@ constructor( ) } } } val TileGrid = @Composable { Box { Loading Loading @@ -1243,28 +1236,3 @@ private fun interactionsConfig() = private inline val alwaysCompose get() = Flags.alwaysComposeQsUiFragment() /** * Forces the configuration and themes to be dark theme. This is needed in order to have * [colorResource] retrieve the dark mode colors. * * This should be removed when we remove the force dark mode in [PlatformTheme] at the root of the * compose hierarchy. */ @Composable private fun AlwaysDarkMode(content: @Composable () -> Unit) { val currentConfig = LocalConfiguration.current val darkConfig = Configuration(currentConfig).apply { uiMode = (uiMode and (Configuration.UI_MODE_NIGHT_MASK.inv())) or Configuration.UI_MODE_NIGHT_YES } val newContext = LocalContext.current.createConfigurationContext(darkConfig) CompositionLocalProvider( LocalConfiguration provides darkConfig, LocalContext provides newContext, ) { content() } }
packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt +85 −45 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Clear import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton Loading @@ -89,6 +90,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.CornerRadius import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.isSpecified import androidx.compose.ui.graphics.Color Loading @@ -115,6 +117,7 @@ import androidx.compose.ui.unit.sp import androidx.compose.ui.util.fastMap import com.android.compose.gesture.effect.rememberOffsetOverscrollEffectFactory import com.android.compose.modifiers.height import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.common.ui.compose.load import com.android.systemui.qs.panels.shared.model.SizedTile import com.android.systemui.qs.panels.shared.model.SizedTileImpl Loading @@ -132,6 +135,7 @@ import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaul import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.AUTO_SCROLL_SPEED import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.AvailableTilesGridMinHeight import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.CurrentTilesGridPadding import com.android.systemui.qs.panels.ui.compose.infinitegrid.EditModeTileDefaults.GridBackgroundCornerRadius import com.android.systemui.qs.panels.ui.compose.selection.InteractiveTileContainer import com.android.systemui.qs.panels.ui.compose.selection.MutableSelectionState import com.android.systemui.qs.panels.ui.compose.selection.ResizingState Loading Loading @@ -164,14 +168,27 @@ object TileType @OptIn(ExperimentalMaterial3Api::class) @Composable private fun EditModeTopBar(onStopEditing: () -> Unit, onReset: (() -> Unit)?) { val primaryContainerColor = MaterialTheme.colorScheme.primaryContainer TopAppBar( colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent), title = { Text(text = stringResource(id = R.string.qs_edit)) }, colors = TopAppBarDefaults.topAppBarColors( containerColor = Color.Transparent, titleContentColor = MaterialTheme.colorScheme.onSurface, ), title = { Text( text = stringResource(id = R.string.qs_edit), modifier = Modifier.padding(start = 24.dp), ) }, navigationIcon = { IconButton(onClick = onStopEditing) { IconButton( onClick = onStopEditing, modifier = Modifier.drawBehind { drawCircle(primaryContainerColor) }, ) { Icon( Icons.AutoMirrored.Filled.ArrowBack, tint = MaterialTheme.colorScheme.onSurface, contentDescription = stringResource(id = com.android.internal.R.string.action_bar_up_description), ) Loading @@ -179,11 +196,19 @@ private fun EditModeTopBar(onStopEditing: () -> Unit, onReset: (() -> Unit)?) { }, actions = { if (onReset != null) { TextButton(onClick = onReset) { TextButton( onClick = onReset, colors = ButtonDefaults.textButtonColors( containerColor = MaterialTheme.colorScheme.primary, contentColor = MaterialTheme.colorScheme.onPrimary, ), ) { Text(stringResource(id = com.android.internal.R.string.reset)) } } }, modifier = Modifier.padding(vertical = 8.dp), ) } Loading Loading @@ -247,7 +272,7 @@ fun DefaultEditTileGrid( targetState = listState.dragInProgress || selectionState.selected, label = "QSEditHeader", contentAlignment = Alignment.Center, modifier = Modifier.fillMaxWidth().heightIn(min = 80.dp), modifier = Modifier.fillMaxWidth().heightIn(min = 48.dp), ) { showRemoveTarget -> EditGridHeader { if (showRemoveTarget) { Loading Loading @@ -292,10 +317,6 @@ fun DefaultEditTileGrid( spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin)), modifier = modifier.fillMaxSize(), ) { EditGridHeader { Text(text = stringResource(id = R.string.drag_to_add_tiles)) } val availableTiles = remember { mutableStateListOf<AvailableTileGridCell>().apply { addAll(toAvailableTiles(listState.tiles, otherTiles)) Loading Loading @@ -374,9 +395,7 @@ private fun EditGridHeader( modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit, ) { CompositionLocalProvider( LocalContentColor provides MaterialTheme.colorScheme.onBackground.copy(alpha = .5f) ) { CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) { Box(contentAlignment = Alignment.Center, modifier = modifier.fillMaxWidth()) { content() } } } Loading Loading @@ -423,6 +442,7 @@ private fun CurrentTilesGrid( listState.tiles.fastMap { Pair(it, BounceableTileViewModel()) } } val primaryColor = MaterialTheme.colorScheme.primary TileLazyGrid( state = gridState, columns = GridCells.Fixed(columns), Loading @@ -431,9 +451,9 @@ private fun CurrentTilesGrid( Modifier.fillMaxWidth() .height { totalHeight.roundToPx() } .border( width = 1.dp, color = MaterialTheme.colorScheme.onBackground.copy(alpha = .5f), shape = RoundedCornerShape((TileHeight / 2) + CurrentTilesGridPadding), width = 2.dp, color = primaryColor, shape = RoundedCornerShape(GridBackgroundCornerRadius), ) .dragAndDropTileList(gridState, { gridContentOffset }, listState) { spec -> onSetTiles(currentListState.tileSpecs()) Loading @@ -442,6 +462,13 @@ private fun CurrentTilesGrid( .onGloballyPositioned { coordinates -> gridContentOffset = coordinates.positionInRoot() } .drawBehind { drawRoundRect( primaryColor, cornerRadius = CornerRadius(GridBackgroundCornerRadius.toPx()), alpha = .15f, ) } .testTag(CURRENT_TILES_GRID_TEST_TAG), ) { EditTiles(cells, listState, selectionState, coroutineScope, largeTilesSpan, onRemoveTile) { Loading Loading @@ -472,7 +499,6 @@ private fun AvailableTileGrid( remember(tiles.fastMap { it.tile.category }, tiles.fastMap { it.tile.label }) { groupAndSort(tiles) } val labelColors = EditModeTileDefaults.editTileColors() // Available tiles Column( Loading @@ -483,12 +509,24 @@ private fun AvailableTileGrid( ) { groupedTiles.forEach { (category, tiles) -> key(category) { val surfaceColor = MaterialTheme.colorScheme.surface Column( verticalArrangement = spacedBy(16.dp), modifier = Modifier.drawBehind { drawRoundRect( surfaceColor, cornerRadius = CornerRadius(GridBackgroundCornerRadius.toPx()), alpha = .32f, ) } .padding(16.dp), ) { Text( text = category.label.load() ?: "", fontSize = 20.sp, color = labelColors.label, modifier = Modifier.fillMaxWidth().padding(start = 16.dp, bottom = 8.dp, top = 8.dp), color = MaterialTheme.colorScheme.onSurface, modifier = Modifier.fillMaxWidth().padding(start = 8.dp, bottom = 16.dp), ) tiles.chunked(columns).forEach { row -> Row( Loading @@ -515,6 +553,7 @@ private fun AvailableTileGrid( } } } } fun gridHeight(rows: Int, tileHeight: Dp, tilePadding: Dp, gridPadding: Dp): Dp { return ((tileHeight + tilePadding) * rows) + gridPadding * 2 Loading Loading @@ -764,7 +803,7 @@ private fun AvailableTileGridCell( color = colors.label, overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Center, modifier = Modifier.align(Alignment.Center), modifier = Modifier.align(Alignment.TopCenter), ) } } Loading Loading @@ -864,15 +903,16 @@ private object EditModeTileDefaults { const val AUTO_SCROLL_SPEED = 2 // 2ms per pixel val CurrentTilesGridPadding = 10.dp val AvailableTilesGridMinHeight = 200.dp val GridBackgroundCornerRadius = 42.dp @Composable fun editTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surfaceVariant, iconBackground = MaterialTheme.colorScheme.surfaceVariant, label = MaterialTheme.colorScheme.onSurfaceVariant, secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, icon = MaterialTheme.colorScheme.onSurfaceVariant, background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = Color.Transparent, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onSurface, ) } Loading
packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt +26 −18 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.service.quicksettings.Tile.STATE_ACTIVE import android.service.quicksettings.Tile.STATE_INACTIVE import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable Loading Loading @@ -59,6 +60,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalResources import androidx.compose.ui.semantics.Role Loading @@ -75,6 +77,7 @@ import com.android.app.tracing.coroutines.launchTraced as launch import com.android.compose.animation.Expandable import com.android.compose.animation.bounceable import com.android.compose.modifiers.thenIf import com.android.compose.theme.LocalAndroidColorScheme import com.android.systemui.Flags import com.android.systemui.animation.Expandable import com.android.systemui.common.shared.model.Icon Loading Loading @@ -165,6 +168,7 @@ fun Tile( // TODO(b/361789146): Draw the shapes instead of clipping val tileShape by TileDefaults.animateTileShapeAsState(uiState.state) val animatedColor by animateColorAsState(colors.background, label = "QSTileBackgroundColor") val animatedAlpha by animateFloatAsState(colors.alpha, label = "QSTileAlpha") TileExpandable( color = { animatedColor }, Loading @@ -181,7 +185,8 @@ fun Tile( nextBounceable = currentBounceableInfo.nextTile, orientation = Orientation.Horizontal, bounceEnd = currentBounceableInfo.bounceEnd, ), ) .graphicsLayer { alpha = animatedAlpha }, ) { expandable -> val longClick: (() -> Unit)? = { Loading Loading @@ -370,6 +375,7 @@ data class TileColors( val label: Color, val secondaryLabel: Color, val icon: Color, val alpha: Float = 1f, ) private object TileDefaults { Loading @@ -393,10 +399,10 @@ private object TileDefaults { @ReadOnlyComposable fun activeDualTargetTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surfaceVariant, background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = MaterialTheme.colorScheme.primary, label = MaterialTheme.colorScheme.onSurfaceVariant, secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onPrimary, ) Loading @@ -404,34 +410,36 @@ private object TileDefaults { @ReadOnlyComposable fun inactiveDualTargetTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surfaceVariant, iconBackground = MaterialTheme.colorScheme.surfaceContainerHighest, label = MaterialTheme.colorScheme.onSurfaceVariant, secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, icon = MaterialTheme.colorScheme.onSurfaceVariant, background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = LocalAndroidColorScheme.current.surfaceEffect3, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onSurface, ) @Composable @ReadOnlyComposable fun inactiveTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surfaceVariant, iconBackground = MaterialTheme.colorScheme.surfaceVariant, label = MaterialTheme.colorScheme.onSurfaceVariant, secondaryLabel = MaterialTheme.colorScheme.onSurfaceVariant, icon = MaterialTheme.colorScheme.onSurfaceVariant, background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = Color.Transparent, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onSurface, ) @Composable @ReadOnlyComposable fun unavailableTileColors(): TileColors = TileColors( background = MaterialTheme.colorScheme.surface, iconBackground = MaterialTheme.colorScheme.surface, fun unavailableTileColors(): TileColors { return TileColors( background = LocalAndroidColorScheme.current.surfaceEffect2, iconBackground = LocalAndroidColorScheme.current.surfaceEffect2, label = MaterialTheme.colorScheme.onSurface, secondaryLabel = MaterialTheme.colorScheme.onSurface, icon = MaterialTheme.colorScheme.onSurface, alpha = .38f, ) } @Composable @ReadOnlyComposable Loading
packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/selection/Selection.kt +5 −4 Original line number Diff line number Diff line Loading @@ -62,7 +62,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.toSize import androidx.compose.ui.zIndex import com.android.compose.modifiers.size import com.android.compose.modifiers.thenIf import com.android.systemui.qs.panels.ui.compose.infinitegrid.CommonTileDefaults.InactiveCornerRadius import com.android.systemui.qs.panels.ui.compose.selection.SelectionDefaults.BADGE_ANGLE_RAD Loading Loading @@ -155,6 +154,7 @@ fun InteractiveTileContainer( Icon( Icons.Default.Remove, contentDescription = null, tint = MaterialTheme.colorScheme.onPrimaryContainer, modifier = Modifier.size(size).align(Alignment.Center).graphicsLayer { this.alpha = badgeIconAlpha Loading Loading @@ -218,14 +218,15 @@ fun StaticTileBadge( ) } ) { val secondaryColor = MaterialTheme.colorScheme.secondary val size = with(LocalDensity.current) { BadgeIconSize.toDp() } val primaryColor = MaterialTheme.colorScheme.primary Icon( icon, contentDescription = contentDescription, tint = MaterialTheme.colorScheme.onPrimary, modifier = Modifier.size(size).align(Alignment.Center).drawBehind { drawCircle(secondaryColor, radius = BadgeSize.toPx() / 2) drawCircle(primaryColor, radius = BadgeSize.toPx() / 2) }, ) } Loading Loading @@ -291,7 +292,7 @@ private fun Transition<TileState>.animateColor(): State<Color> { return animateColor { state -> when (state) { None -> Color.Transparent Removable -> MaterialTheme.colorScheme.secondary Removable -> MaterialTheme.colorScheme.primaryContainer Selected -> MaterialTheme.colorScheme.primary } } Loading
packages/SystemUI/tests/src/com/android/systemui/qs/panels/ui/compose/DragAndDropTest.kt +16 −13 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import androidx.compose.ui.text.AnnotatedString import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.FlakyTest import androidx.test.filters.SmallTest import com.android.compose.theme.PlatformTheme import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon Loading @@ -55,6 +56,7 @@ class DragAndDropTest : SysuiTestCase() { listState: EditTileListState, onSetTiles: (List<TileSpec>) -> Unit, ) { PlatformTheme { DefaultEditTileGrid( listState = listState, otherTiles = listOf(), Loading @@ -69,6 +71,7 @@ class DragAndDropTest : SysuiTestCase() { onReset = null, ) } } @Test fun draggedTile_shouldDisappear() { Loading