Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/Chip.kt +9 −3 Original line number Diff line number Diff line Loading @@ -18,10 +18,12 @@ package com.android.systemui.ambientcue.ui.compose import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape Loading Loading @@ -50,14 +52,18 @@ fun Chip(action: ActionViewModel, modifier: Modifier = Modifier) { modifier .clip(RoundedCornerShape(24.dp)) .background(backgroundColor) .defaultMinSize(minHeight = 48.dp) .combinedClickable(onClick = action.onClick, onLongClick = action.onLongClick) .padding(horizontal = 8.dp, vertical = 12.dp), .padding(start = 12.dp, end = 16.dp, top = 4.dp, bottom = 4.dp), ) { val painter = rememberDrawablePainter(action.icon) Image( painter = painter, contentDescription = action.label, modifier = Modifier.size(24.dp).clip(CircleShape), modifier = Modifier.size(24.dp) .border(0.75.dp, MaterialTheme.colorScheme.outline, CircleShape) .clip(CircleShape), ) Column { Loading @@ -75,7 +81,7 @@ fun Chip(action: ActionViewModel, modifier: Modifier = Modifier) { style = MaterialTheme.typography.labelLarge, color = outlineColor, maxLines = 1, modifier = Modifier.alpha(0.4f), modifier = Modifier.alpha(0.8f), overflow = TextOverflow.Ellipsis, ) } Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/NavBarPill.kt +80 −22 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box Loading @@ -44,15 +45,17 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEachIndexed import androidx.compose.ui.util.lerp import com.android.compose.PlatformIconButton import com.android.compose.ui.graphics.painter.rememberDrawablePainter Loading @@ -70,7 +73,8 @@ fun NavBarPill( onClick: () -> Unit = {}, onCloseClick: () -> Unit = {}, ) { val maxPillWidth = 247.dp val configuration = LocalConfiguration.current val maxPillWidth = (configuration.screenWidthDp * 0.65f).dp val outlineColor = MaterialTheme.colorScheme.onBackground val backgroundColor = MaterialTheme.colorScheme.background Loading Loading @@ -112,7 +116,7 @@ fun NavBarPill( Spacer(modifier = Modifier.size(closeButtonSize)) Row( horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, modifier = Modifier.clip(RoundedCornerShape(16.dp)) Loading @@ -120,42 +124,96 @@ fun NavBarPill( .background(backgroundColor) .animatedActionBorder( strokeWidth = 1.dp, strokeColor = outlineColor, cornerRadius = 16.dp, visible = visible, ) .then(if (expanded) Modifier else Modifier.clickable { onClick() }) .padding(horizontal = 8.dp, vertical = 6.dp) .padding(3.dp) .onGloballyPositioned { expandedSize = it.size }, ) { // Should have at most 1 expanded chip var expandedChip = false actions.fastForEach { action -> actions.fastForEachIndexed { index, action -> val hasAttribution = action.attribution != null Row( horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally), Arrangement.spacedBy(3.dp, Alignment.CenterHorizontally), verticalAlignment = Alignment.CenterVertically, modifier = if (hasAttribution) Modifier.weight(1f, false) else Modifier.width(IntrinsicSize.Max), ) { if ((actions.size == 1 || hasAttribution) && !expandedChip) { expandedChip = true val hasBackground = actions.size > 1 Row( horizontalArrangement = Arrangement.spacedBy(4.dp), modifier = Modifier.padding(end = 3.dp) .clip(RoundedCornerShape(16.dp)) .background( if (hasBackground) { MaterialTheme.colorScheme.onSecondary } else { Color.Transparent } ) .padding(6.dp), ) { Image( painter = rememberDrawablePainter(action.icon), contentDescription = action.label, modifier = Modifier.size(16.dp).clip(CircleShape), modifier = Modifier.size(16.dp) .border( width = 0.75.dp, color = MaterialTheme.colorScheme.outline, shape = CircleShape, ) .clip(CircleShape), ) if ((actions.size == 1 || hasAttribution) && !expandedChip) { expandedChip = true Text( text = action.label, style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelMedium, maxLines = 1, overflow = TextOverflow.Ellipsis, color = outlineColor, modifier = Modifier.widthIn(0.dp, maxPillWidth * 0.5f), ) if (hasAttribution) { Text( text = action.attribution!!, style = MaterialTheme.typography.labelMedium, maxLines = 1, overflow = TextOverflow.Ellipsis, color = outlineColor, modifier = Modifier.alpha(0.4f), ) } } } else { Image( painter = rememberDrawablePainter(action.icon), contentDescription = action.label, modifier = Modifier.then( if (index == 0) { Modifier.padding(start = 5.dp) } else if (index == actions.size - 1) { Modifier.padding(end = 5.dp) } else { Modifier } ) .padding(3.dp) .size(16.dp) .border( width = 0.75.dp, color = MaterialTheme.colorScheme.outline, shape = CircleShape, ) .clip(CircleShape), ) } } } Loading @@ -165,8 +223,8 @@ fun NavBarPill( modifier = Modifier.size(closeButtonSize) .clip(CircleShape) .background(backgroundColor) .padding(8.dp), .background(backgroundColor.copy(alpha = 0.7f)) .padding(6.dp), iconResource = R.drawable.ic_close_white_rounded, colors = IconButtonColors( Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/ShortPill.kt +6 −7 Original line number Diff line number Diff line Loading @@ -94,12 +94,7 @@ fun ShortPill( Modifier.graphicsLayer { alpha = enterProgress * expansionAlpha } .clip(RoundedCornerShape(16.dp)) .background(backgroundColor) .animatedActionBorder( strokeWidth = 2.dp, strokeColor = outlineColor, cornerRadius = 16.dp, visible = visible, ) .animatedActionBorder(strokeWidth = 1.dp, cornerRadius = 16.dp, visible = visible) .widthIn(0.dp, minSize * 2) .clickable { onClick() } .padding(4.dp) Loading Loading @@ -195,7 +190,11 @@ private fun Icon(action: ActionViewModel, backgroundColor: Color, modifier: Modi modifier = modifier .size(18.dp) .border(1.dp, backgroundColor, CircleShape) .border( width = 0.75.dp, color = MaterialTheme.colorScheme.outline, shape = CircleShape, ) .padding(1.dp) .clip(CircleShape) .background(backgroundColor), Loading packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/modifier/AnimatedActionBorder.kt +10 −18 Original line number Diff line number Diff line Loading @@ -46,7 +46,6 @@ import kotlinx.coroutines.launch @Composable fun Modifier.animatedActionBorder( strokeWidth: Dp, strokeColor: Color, cornerRadius: Dp, visible: Boolean = true, ): Modifier { Loading Loading @@ -122,6 +121,7 @@ fun Modifier.animatedActionBorder( tileMode = TileMode.Clamp, ) if (gradientOutlineFadeOut > 0) { drawRoundRect( brush = gradientBrush, topLeft = topLeft, Loading @@ -130,15 +130,7 @@ fun Modifier.animatedActionBorder( alpha = gradientOutlineFadeOut, style = strokeStyle, ) drawRoundRect( color = strokeColor, topLeft = topLeft, size = Size(size.width - strokeWidthPx, size.height - strokeWidthPx), cornerRadius = CornerRadius(cornerRadiusPx), alpha = solidOutlineFadeIn, style = strokeStyle, ) } drawContent() } Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/Chip.kt +9 −3 Original line number Diff line number Diff line Loading @@ -18,10 +18,12 @@ package com.android.systemui.ambientcue.ui.compose import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape Loading Loading @@ -50,14 +52,18 @@ fun Chip(action: ActionViewModel, modifier: Modifier = Modifier) { modifier .clip(RoundedCornerShape(24.dp)) .background(backgroundColor) .defaultMinSize(minHeight = 48.dp) .combinedClickable(onClick = action.onClick, onLongClick = action.onLongClick) .padding(horizontal = 8.dp, vertical = 12.dp), .padding(start = 12.dp, end = 16.dp, top = 4.dp, bottom = 4.dp), ) { val painter = rememberDrawablePainter(action.icon) Image( painter = painter, contentDescription = action.label, modifier = Modifier.size(24.dp).clip(CircleShape), modifier = Modifier.size(24.dp) .border(0.75.dp, MaterialTheme.colorScheme.outline, CircleShape) .clip(CircleShape), ) Column { Loading @@ -75,7 +81,7 @@ fun Chip(action: ActionViewModel, modifier: Modifier = Modifier) { style = MaterialTheme.typography.labelLarge, color = outlineColor, maxLines = 1, modifier = Modifier.alpha(0.4f), modifier = Modifier.alpha(0.8f), overflow = TextOverflow.Ellipsis, ) } Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/NavBarPill.kt +80 −22 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box Loading @@ -44,15 +45,17 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEachIndexed import androidx.compose.ui.util.lerp import com.android.compose.PlatformIconButton import com.android.compose.ui.graphics.painter.rememberDrawablePainter Loading @@ -70,7 +73,8 @@ fun NavBarPill( onClick: () -> Unit = {}, onCloseClick: () -> Unit = {}, ) { val maxPillWidth = 247.dp val configuration = LocalConfiguration.current val maxPillWidth = (configuration.screenWidthDp * 0.65f).dp val outlineColor = MaterialTheme.colorScheme.onBackground val backgroundColor = MaterialTheme.colorScheme.background Loading Loading @@ -112,7 +116,7 @@ fun NavBarPill( Spacer(modifier = Modifier.size(closeButtonSize)) Row( horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, modifier = Modifier.clip(RoundedCornerShape(16.dp)) Loading @@ -120,42 +124,96 @@ fun NavBarPill( .background(backgroundColor) .animatedActionBorder( strokeWidth = 1.dp, strokeColor = outlineColor, cornerRadius = 16.dp, visible = visible, ) .then(if (expanded) Modifier else Modifier.clickable { onClick() }) .padding(horizontal = 8.dp, vertical = 6.dp) .padding(3.dp) .onGloballyPositioned { expandedSize = it.size }, ) { // Should have at most 1 expanded chip var expandedChip = false actions.fastForEach { action -> actions.fastForEachIndexed { index, action -> val hasAttribution = action.attribution != null Row( horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally), Arrangement.spacedBy(3.dp, Alignment.CenterHorizontally), verticalAlignment = Alignment.CenterVertically, modifier = if (hasAttribution) Modifier.weight(1f, false) else Modifier.width(IntrinsicSize.Max), ) { if ((actions.size == 1 || hasAttribution) && !expandedChip) { expandedChip = true val hasBackground = actions.size > 1 Row( horizontalArrangement = Arrangement.spacedBy(4.dp), modifier = Modifier.padding(end = 3.dp) .clip(RoundedCornerShape(16.dp)) .background( if (hasBackground) { MaterialTheme.colorScheme.onSecondary } else { Color.Transparent } ) .padding(6.dp), ) { Image( painter = rememberDrawablePainter(action.icon), contentDescription = action.label, modifier = Modifier.size(16.dp).clip(CircleShape), modifier = Modifier.size(16.dp) .border( width = 0.75.dp, color = MaterialTheme.colorScheme.outline, shape = CircleShape, ) .clip(CircleShape), ) if ((actions.size == 1 || hasAttribution) && !expandedChip) { expandedChip = true Text( text = action.label, style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelMedium, maxLines = 1, overflow = TextOverflow.Ellipsis, color = outlineColor, modifier = Modifier.widthIn(0.dp, maxPillWidth * 0.5f), ) if (hasAttribution) { Text( text = action.attribution!!, style = MaterialTheme.typography.labelMedium, maxLines = 1, overflow = TextOverflow.Ellipsis, color = outlineColor, modifier = Modifier.alpha(0.4f), ) } } } else { Image( painter = rememberDrawablePainter(action.icon), contentDescription = action.label, modifier = Modifier.then( if (index == 0) { Modifier.padding(start = 5.dp) } else if (index == actions.size - 1) { Modifier.padding(end = 5.dp) } else { Modifier } ) .padding(3.dp) .size(16.dp) .border( width = 0.75.dp, color = MaterialTheme.colorScheme.outline, shape = CircleShape, ) .clip(CircleShape), ) } } } Loading @@ -165,8 +223,8 @@ fun NavBarPill( modifier = Modifier.size(closeButtonSize) .clip(CircleShape) .background(backgroundColor) .padding(8.dp), .background(backgroundColor.copy(alpha = 0.7f)) .padding(6.dp), iconResource = R.drawable.ic_close_white_rounded, colors = IconButtonColors( Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/ShortPill.kt +6 −7 Original line number Diff line number Diff line Loading @@ -94,12 +94,7 @@ fun ShortPill( Modifier.graphicsLayer { alpha = enterProgress * expansionAlpha } .clip(RoundedCornerShape(16.dp)) .background(backgroundColor) .animatedActionBorder( strokeWidth = 2.dp, strokeColor = outlineColor, cornerRadius = 16.dp, visible = visible, ) .animatedActionBorder(strokeWidth = 1.dp, cornerRadius = 16.dp, visible = visible) .widthIn(0.dp, minSize * 2) .clickable { onClick() } .padding(4.dp) Loading Loading @@ -195,7 +190,11 @@ private fun Icon(action: ActionViewModel, backgroundColor: Color, modifier: Modi modifier = modifier .size(18.dp) .border(1.dp, backgroundColor, CircleShape) .border( width = 0.75.dp, color = MaterialTheme.colorScheme.outline, shape = CircleShape, ) .padding(1.dp) .clip(CircleShape) .background(backgroundColor), Loading
packages/SystemUI/compose/features/src/com/android/systemui/ambientcue/ui/compose/modifier/AnimatedActionBorder.kt +10 −18 Original line number Diff line number Diff line Loading @@ -46,7 +46,6 @@ import kotlinx.coroutines.launch @Composable fun Modifier.animatedActionBorder( strokeWidth: Dp, strokeColor: Color, cornerRadius: Dp, visible: Boolean = true, ): Modifier { Loading Loading @@ -122,6 +121,7 @@ fun Modifier.animatedActionBorder( tileMode = TileMode.Clamp, ) if (gradientOutlineFadeOut > 0) { drawRoundRect( brush = gradientBrush, topLeft = topLeft, Loading @@ -130,15 +130,7 @@ fun Modifier.animatedActionBorder( alpha = gradientOutlineFadeOut, style = strokeStyle, ) drawRoundRect( color = strokeColor, topLeft = topLeft, size = Size(size.width - strokeWidthPx, size.height - strokeWidthPx), cornerRadius = CornerRadius(cornerRadiusPx), alpha = solidOutlineFadeIn, style = strokeStyle, ) } drawContent() } Loading