summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Caitlin Shkuratov <caitlinshk@google.com> 2025-02-10 13:10:06 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-02-10 13:10:06 -0800
commita015d7eeca96aae598e88d2e40284f860b1d6cf6 (patch)
treedcf12c66a84ebdf0eb1e96b7de2d0fca6b60cf18
parent289ca076a2774e88e3e228f75a0f08ba38e63f24 (diff)
parent31f9b781897388834a7622b53d1c35c4aac73b8a (diff)
Merge changes from topics "caitlinshk-chips-color", "caitlinshk-text-truncation" into main
* changes: [SB][Notif] Hide text in chips if not *all* of the text fits. [SB][Notif] Add a subtle outline to notification chips. [SB][Notif] Update notif chips to use system theme colors.
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt75
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt7
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelperTest.kt21
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt8
-rw-r--r--packages/SystemUI/res/layout/ongoing_activity_chip_content.xml7
-rw-r--r--packages/SystemUI/res/values/dimens.xml1
-rw-r--r--packages/SystemUI/res/values/styles.xml9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt125
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt42
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelper.kt10
14 files changed, 150 insertions, 216 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
index dbe8f8226d43..c7b3175a636f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModelTest.kt
@@ -31,7 +31,6 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.activityStarter
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView
-import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
@@ -265,91 +264,25 @@ class CallChipViewModelTest : SysuiTestCase() {
}
@Test
- fun chip_positiveStartTime_notPromoted_colorsAreThemed() =
+ fun chip_positiveStartTime_colorsAreAccentThemed() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
repo.setOngoingCallState(inCallModel(startTimeMs = 1000, promotedContent = null))
assertThat((latest as OngoingActivityChipModel.Active).colors)
- .isEqualTo(ColorsModel.Themed)
+ .isEqualTo(ColorsModel.AccentThemed)
}
@Test
- fun chip_zeroStartTime_notPromoted_colorsAreThemed() =
+ fun chip_zeroStartTime_colorsAreAccentThemed() =
testScope.runTest {
val latest by collectLastValue(underTest.chip)
repo.setOngoingCallState(inCallModel(startTimeMs = 0, promotedContent = null))
assertThat((latest as OngoingActivityChipModel.Active).colors)
- .isEqualTo(ColorsModel.Themed)
- }
-
- @Test
- @DisableFlags(StatusBarNotifChips.FLAG_NAME)
- fun chip_positiveStartTime_promoted_notifChipsFlagOff_colorsAreThemed() =
- testScope.runTest {
- val latest by collectLastValue(underTest.chip)
-
- repo.setOngoingCallState(
- inCallModel(startTimeMs = 1000, promotedContent = PROMOTED_CONTENT_WITH_COLOR)
- )
-
- assertThat((latest as OngoingActivityChipModel.Active).colors)
- .isEqualTo(ColorsModel.Themed)
- }
-
- @Test
- @DisableFlags(StatusBarNotifChips.FLAG_NAME)
- fun chip_zeroStartTime_promoted_notifChipsFlagOff_colorsAreThemed() =
- testScope.runTest {
- val latest by collectLastValue(underTest.chip)
-
- repo.setOngoingCallState(
- inCallModel(startTimeMs = 0, promotedContent = PROMOTED_CONTENT_WITH_COLOR)
- )
-
- assertThat((latest as OngoingActivityChipModel.Active).colors)
- .isEqualTo(ColorsModel.Themed)
- }
-
- @Test
- @EnableFlags(StatusBarNotifChips.FLAG_NAME)
- fun chip_positiveStartTime_promoted_notifChipsFlagOn_colorsAreCustom() =
- testScope.runTest {
- val latest by collectLastValue(underTest.chip)
-
- repo.setOngoingCallState(
- inCallModel(startTimeMs = 1000, promotedContent = PROMOTED_CONTENT_WITH_COLOR)
- )
-
- assertThat((latest as OngoingActivityChipModel.Active).colors)
- .isEqualTo(
- ColorsModel.Custom(
- backgroundColorInt = PROMOTED_BACKGROUND_COLOR,
- primaryTextColorInt = PROMOTED_PRIMARY_TEXT_COLOR,
- )
- )
- }
-
- @Test
- @EnableFlags(StatusBarNotifChips.FLAG_NAME)
- fun chip_zeroStartTime_promoted_notifChipsFlagOff_colorsAreCustom() =
- testScope.runTest {
- val latest by collectLastValue(underTest.chip)
-
- repo.setOngoingCallState(
- inCallModel(startTimeMs = 0, promotedContent = PROMOTED_CONTENT_WITH_COLOR)
- )
-
- assertThat((latest as OngoingActivityChipModel.Active).colors)
- .isEqualTo(
- ColorsModel.Custom(
- backgroundColorInt = PROMOTED_BACKGROUND_COLOR,
- primaryTextColorInt = PROMOTED_PRIMARY_TEXT_COLOR,
- )
- )
+ .isEqualTo(ColorsModel.AccentThemed)
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
index 192ad879891f..aaa9b58a45df 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModelTest.kt
@@ -186,7 +186,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
@Test
@DisableFlags(FLAG_PROMOTE_NOTIFICATIONS_AUTOMATICALLY)
- fun chips_onePromotedNotif_colorMatches() =
+ fun chips_onePromotedNotif_colorIsSystemThemed() =
kosmos.runTest {
val latest by collectLastValue(underTest.chips)
@@ -209,10 +209,7 @@ class NotifChipsViewModelTest : SysuiTestCase() {
)
assertThat(latest).hasSize(1)
- val colors = latest!![0].colors
- assertThat(colors).isInstanceOf(ColorsModel.Custom::class.java)
- assertThat((colors as ColorsModel.Custom).backgroundColorInt).isEqualTo(56)
- assertThat((colors as ColorsModel.Custom).primaryTextColorInt).isEqualTo(89)
+ assertThat(latest!![0].colors).isEqualTo(ColorsModel.SystemThemed)
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelperTest.kt
index d727089094f0..9ec5a42714bf 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelperTest.kt
@@ -52,24 +52,13 @@ class ChipTextTruncationHelperTest : SysuiTestCase() {
}
@Test
- fun shouldShowText_desiredSlightlyLargerThanMax_true() {
+ fun shouldShowText_desiredMoreThanMax_false() {
val result =
underTest.shouldShowText(
desiredTextWidthPx = (MAX_WIDTH * 1.1).toInt(),
widthMeasureSpec = UNLIMITED_WIDTH_SPEC,
)
- assertThat(result).isTrue()
- }
-
- @Test
- fun shouldShowText_desiredMoreThanTwiceMax_false() {
- val result =
- underTest.shouldShowText(
- desiredTextWidthPx = (MAX_WIDTH * 2.2).toInt(),
- widthMeasureSpec = UNLIMITED_WIDTH_SPEC,
- )
-
assertThat(result).isFalse()
}
@@ -80,8 +69,8 @@ class ChipTextTruncationHelperTest : SysuiTestCase() {
View.MeasureSpec.makeMeasureSpec(MAX_WIDTH / 2, View.MeasureSpec.AT_MOST)
)
- // WHEN desired is more than twice the smallerWidthSpec
- val desiredWidth = (MAX_WIDTH * 1.1).toInt()
+ // WHEN desired is more than the smallerWidthSpec
+ val desiredWidth = ((MAX_WIDTH / 2) * 1.1).toInt()
val result =
underTest.shouldShowText(
@@ -100,8 +89,8 @@ class ChipTextTruncationHelperTest : SysuiTestCase() {
View.MeasureSpec.makeMeasureSpec(MAX_WIDTH * 3, View.MeasureSpec.AT_MOST)
)
- // WHEN desired is more than twice the max
- val desiredWidth = (MAX_WIDTH * 2.2).toInt()
+ // WHEN desired is more than the max
+ val desiredWidth = (MAX_WIDTH * 1.1).toInt()
val result =
underTest.shouldShowText(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
index 60030ad4e428..e3a84fd2c2eb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/ChipTransitionHelperTest.kt
@@ -54,7 +54,7 @@ class ChipTransitionHelperTest : SysuiTestCase() {
OngoingActivityChipModel.Active.Timer(
key = KEY,
icon = createIcon(R.drawable.ic_cake),
- colors = ColorsModel.Themed,
+ colors = ColorsModel.AccentThemed,
startTimeMs = 100L,
onClickListenerLegacy = null,
clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
@@ -68,7 +68,7 @@ class ChipTransitionHelperTest : SysuiTestCase() {
OngoingActivityChipModel.Active.IconOnly(
key = KEY,
icon = createIcon(R.drawable.ic_hotspot),
- colors = ColorsModel.Themed,
+ colors = ColorsModel.AccentThemed,
onClickListenerLegacy = null,
clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
)
@@ -90,7 +90,7 @@ class ChipTransitionHelperTest : SysuiTestCase() {
OngoingActivityChipModel.Active.Timer(
key = KEY,
icon = createIcon(R.drawable.ic_cake),
- colors = ColorsModel.Themed,
+ colors = ColorsModel.AccentThemed,
startTimeMs = 100L,
onClickListenerLegacy = null,
clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
@@ -132,7 +132,7 @@ class ChipTransitionHelperTest : SysuiTestCase() {
OngoingActivityChipModel.Active.Timer(
key = KEY,
icon = createIcon(R.drawable.ic_cake),
- colors = ColorsModel.Themed,
+ colors = ColorsModel.AccentThemed,
startTimeMs = 100L,
onClickListenerLegacy = null,
clickBehavior = OngoingActivityChipModel.ClickBehavior.None,
diff --git a/packages/SystemUI/res/layout/ongoing_activity_chip_content.xml b/packages/SystemUI/res/layout/ongoing_activity_chip_content.xml
index 6f42286d9fac..b66a88a3e523 100644
--- a/packages/SystemUI/res/layout/ongoing_activity_chip_content.xml
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip_content.xml
@@ -43,9 +43,6 @@
ongoing_activity_chip_short_time_delta] will ever be shown at one time. -->
<!-- Shows a timer, like 00:01. -->
- <!-- Don't use the LimitedWidth style for the timer because the end of the timer is often
- the most important value. ChipChronometer has the correct logic for when the timer is
- too large for the space allowed. -->
<com.android.systemui.statusbar.chips.ui.view.ChipChronometer
android:id="@+id/ongoing_activity_chip_time"
style="@style/StatusBar.Chip.Text"
@@ -54,14 +51,14 @@
<!-- Shows generic text. -->
<com.android.systemui.statusbar.chips.ui.view.ChipTextView
android:id="@+id/ongoing_activity_chip_text"
- style="@style/StatusBar.Chip.Text.LimitedWidth"
+ style="@style/StatusBar.Chip.Text"
android:visibility="gone"
/>
<!-- Shows a time delta in short form, like "15min" or "1hr". -->
<com.android.systemui.statusbar.chips.ui.view.ChipDateTimeView
android:id="@+id/ongoing_activity_chip_short_time_delta"
- style="@style/StatusBar.Chip.Text.LimitedWidth"
+ style="@style/StatusBar.Chip.Text"
android:visibility="gone"
/>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2d3c07b93cb1..648e4c2e3ac7 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1811,6 +1811,7 @@
<dimen name="ongoing_activity_chip_text_end_padding_for_embedded_padding_icon">6dp</dimen>
<dimen name="ongoing_activity_chip_text_fading_edge_length">12dp</dimen>
<dimen name="ongoing_activity_chip_corner_radius">28dp</dimen>
+ <dimen name="ongoing_activity_chip_outline_width">2px</dimen>
<!-- Status bar user chip -->
<dimen name="status_bar_user_chip_avatar_size">16dp</dimen>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 7f2c89346423..4961a7ece69a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -93,15 +93,6 @@
<item name="android:textColor">?android:attr/colorPrimary</item>
</style>
- <!-- Style for a status bar chip text that has a maximum width. Since there's so little room in
- the status bar chip area, don't ellipsize the text and instead just fade it out a bit at
- the end. -->
- <style name="StatusBar.Chip.Text.LimitedWidth">
- <item name="android:ellipsize">none</item>
- <item name="android:requiresFadingEdge">horizontal</item>
- <item name="android:fadingEdgeLength">@dimen/ongoing_activity_chip_text_fading_edge_length</item>
- </style>
-
<style name="Chipbar" />
<style name="Chipbar.Text" parent="@*android:style/TextAppearance.DeviceDefault.Notification.Title">
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
index a2c0226addfa..f466278e15a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/call/ui/viewmodel/CallChipViewModel.kt
@@ -32,9 +32,7 @@ import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.StatusBarChipLogTags.pad
import com.android.systemui.statusbar.chips.StatusBarChipsLog
import com.android.systemui.statusbar.chips.call.domain.interactor.CallChipInteractor
-import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
-import com.android.systemui.statusbar.chips.ui.model.ColorsModel.Companion.toCustomColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
@@ -86,12 +84,7 @@ constructor(
OngoingActivityChipModel.ChipIcon.SingleColorIcon(phoneIcon)
}
- val colors =
- if (StatusBarNotifChips.isEnabled && state.promotedContent != null) {
- state.promotedContent.toCustomColorsModel()
- } else {
- ColorsModel.Themed
- }
+ val colors = ColorsModel.AccentThemed
// This block mimics OngoingCallController#updateChip.
if (state.startTimeMs <= 0L) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
index 8357df42937e..2d6102e310f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt
@@ -27,7 +27,7 @@ import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.notification.domain.interactor.StatusBarNotificationChipsInteractor
import com.android.systemui.statusbar.chips.notification.domain.model.NotificationChipModel
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
-import com.android.systemui.statusbar.chips.ui.model.ColorsModel.Companion.toCustomColorsModel
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
@@ -85,8 +85,7 @@ constructor(
contentDescription,
)
}
- val colors = this.promotedContent.toCustomColorsModel()
-
+ val colors = ColorsModel.SystemThemed
val clickListener: () -> Unit = {
// The notification pipeline needs everything to run on the main thread, so keep
// this event on the main thread.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
index 456cd121a540..d41353b2c176 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.chips.ui.binder
import android.annotation.IdRes
+import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.GradientDrawable
import android.view.View
@@ -32,6 +33,7 @@ import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips
+import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
@@ -76,8 +78,10 @@ object OngoingActivityChipBinder {
chipTimeView.setTextColor(textColor)
chipTextView.setTextColor(textColor)
chipShortTimeDeltaView.setTextColor(textColor)
- (chipBackgroundView.background as GradientDrawable).color =
- chipModel.colors.background(chipContext)
+ (chipBackgroundView.background as GradientDrawable).setBackgroundColors(
+ chipModel.colors,
+ chipContext,
+ )
}
is OngoingActivityChipModel.Inactive -> {
// The Chronometer should be stopped to prevent leaks -- see b/192243808 and
@@ -460,5 +464,20 @@ object OngoingActivityChipBinder {
chipView.minimumWidth = minimumWidth
}
+ private fun GradientDrawable.setBackgroundColors(colors: ColorsModel, context: Context) {
+ this.color = colors.background(context)
+ val outline = colors.outline(context)
+ if (outline != null) {
+ this.setStroke(
+ context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_outline_width
+ ),
+ outline,
+ )
+ } else {
+ this.setStroke(0, /* color= */ 0)
+ }
+ }
+
@IdRes private val CUSTOM_ICON_VIEW_ID = R.id.ongoing_activity_chip_custom_icon
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt
index 32de0fbfd870..8443d106dfb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/ChipContent.kt
@@ -20,16 +20,9 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawWithCache
-import androidx.compose.ui.graphics.BlendMode
-import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.CompositingStrategy
-import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureResult
import androidx.compose.ui.layout.MeasureScope
@@ -37,6 +30,8 @@ import androidx.compose.ui.node.LayoutModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.text.TextMeasurer
+import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
@@ -83,15 +78,14 @@ fun ChipContent(viewModel: OngoingActivityChipModel.Active, modifier: Modifier =
softWrap = false,
modifier =
modifier
- .customTextContentLayout(
+ .hideTextIfDoesNotFit(
+ text = text,
+ textStyle = textStyle,
+ textMeasurer = textMeasurer,
maxTextWidth = maxTextWidth,
startPadding = startPadding,
endPadding = endPadding,
- ) { constraintWidth ->
- val intrinsicWidth =
- textMeasurer.measure(text, textStyle, softWrap = false).size.width
- intrinsicWidth <= constraintWidth
- }
+ )
.neverDecreaseWidth(),
)
}
@@ -108,7 +102,6 @@ fun ChipContent(viewModel: OngoingActivityChipModel.Active, modifier: Modifier =
}
is OngoingActivityChipModel.Active.Text -> {
- var hasOverflow by remember { mutableStateOf(false) }
val text = viewModel.text
Text(
text = text,
@@ -116,24 +109,14 @@ fun ChipContent(viewModel: OngoingActivityChipModel.Active, modifier: Modifier =
style = textStyle,
softWrap = false,
modifier =
- modifier
- .customTextContentLayout(
- maxTextWidth = maxTextWidth,
- startPadding = startPadding,
- endPadding = endPadding,
- ) { constraintWidth ->
- val intrinsicWidth =
- textMeasurer.measure(text, textStyle, softWrap = false).size.width
- hasOverflow = intrinsicWidth > constraintWidth
- constraintWidth.toFloat() / intrinsicWidth.toFloat() > 0.5f
- }
- .overflowFadeOut(
- hasOverflow = { hasOverflow },
- fadeLength =
- dimensionResource(
- id = R.dimen.ongoing_activity_chip_text_fading_edge_length
- ),
- ),
+ modifier.hideTextIfDoesNotFit(
+ text = text,
+ textStyle = textStyle,
+ textMeasurer = textMeasurer,
+ maxTextWidth = maxTextWidth,
+ startPadding = startPadding,
+ endPadding = endPadding,
+ ),
)
}
@@ -180,45 +163,67 @@ private class NeverDecreaseWidthNode : Modifier.Node(), LayoutModifierNode {
}
/**
- * A custom layout modifier for text that ensures its text is only visible if a provided
- * [shouldShow] callback returns true. Imposes a provided [maxTextWidthPx]. Also, accounts for
- * provided padding values if provided and ensures its text is placed with the provided padding
- * included around it.
+ * A custom layout modifier for text that ensures the text is only visible if it completely fits
+ * within the constrained bounds. Imposes a provided [maxTextWidthPx]. Also, accounts for provided
+ * padding values if provided and ensures its text is placed with the provided padding included
+ * around it.
*/
-private fun Modifier.customTextContentLayout(
+private fun Modifier.hideTextIfDoesNotFit(
+ text: String,
+ textStyle: TextStyle,
+ textMeasurer: TextMeasurer,
maxTextWidth: Dp,
startPadding: Dp = 0.dp,
endPadding: Dp = 0.dp,
- shouldShow: (constraintWidth: Int) -> Boolean,
): Modifier {
return this.then(
- CustomTextContentLayoutElement(maxTextWidth, startPadding, endPadding, shouldShow)
+ HideTextIfDoesNotFitElement(
+ text,
+ textStyle,
+ textMeasurer,
+ maxTextWidth,
+ startPadding,
+ endPadding,
+ )
)
}
-private data class CustomTextContentLayoutElement(
+private data class HideTextIfDoesNotFitElement(
+ val text: String,
+ val textStyle: TextStyle,
+ val textMeasurer: TextMeasurer,
val maxTextWidth: Dp,
val startPadding: Dp,
val endPadding: Dp,
- val shouldShow: (constrainedWidth: Int) -> Boolean,
-) : ModifierNodeElement<CustomTextContentLayoutNode>() {
- override fun create(): CustomTextContentLayoutNode {
- return CustomTextContentLayoutNode(maxTextWidth, startPadding, endPadding, shouldShow)
+) : ModifierNodeElement<HideTextIfDoesNotFitNode>() {
+ override fun create(): HideTextIfDoesNotFitNode {
+ return HideTextIfDoesNotFitNode(
+ text,
+ textStyle,
+ textMeasurer,
+ maxTextWidth,
+ startPadding,
+ endPadding,
+ )
}
- override fun update(node: CustomTextContentLayoutNode) {
- node.shouldShow = shouldShow
+ override fun update(node: HideTextIfDoesNotFitNode) {
+ node.text = text
+ node.textStyle = textStyle
+ node.textMeasurer = textMeasurer
node.maxTextWidth = maxTextWidth
node.startPadding = startPadding
node.endPadding = endPadding
}
}
-private class CustomTextContentLayoutNode(
+private class HideTextIfDoesNotFitNode(
+ var text: String,
+ var textStyle: TextStyle,
+ var textMeasurer: TextMeasurer,
var maxTextWidth: Dp,
var startPadding: Dp,
var endPadding: Dp,
- var shouldShow: (constrainedWidth: Int) -> Boolean,
) : Modifier.Node(), LayoutModifierNode {
override fun MeasureScope.measure(
measurable: Measurable,
@@ -230,9 +235,10 @@ private class CustomTextContentLayoutNode(
.coerceAtLeast(constraints.minWidth)
val placeable = measurable.measure(constraints.copy(maxWidth = maxWidth))
- val height = placeable.height
- val width = placeable.width
- return if (shouldShow(maxWidth)) {
+ val intrinsicWidth = textMeasurer.measure(text, textStyle, softWrap = false).size.width
+ return if (intrinsicWidth <= maxWidth) {
+ val height = placeable.height
+ val width = placeable.width
layout(width + horizontalPadding.roundToPx(), height) {
placeable.place(startPadding.roundToPx(), 0)
}
@@ -241,20 +247,3 @@ private class CustomTextContentLayoutNode(
}
}
}
-
-private fun Modifier.overflowFadeOut(hasOverflow: () -> Boolean, fadeLength: Dp): Modifier {
- return graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen).drawWithCache {
- val width = size.width
- val start = (width - fadeLength.toPx()).coerceAtLeast(0f)
- val gradient =
- Brush.horizontalGradient(
- colors = listOf(Color.Black, Color.Transparent),
- startX = start,
- endX = width,
- )
- onDrawWithContent {
- drawContent()
- if (hasOverflow()) drawRect(brush = gradient, blendMode = BlendMode.DstIn)
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
index 76c53861f0ab..1cdf6800fb97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/compose/OngoingActivityChip.kt
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.chips.ui.compose
import android.content.res.ColorStateList
import android.view.ViewGroup
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
@@ -103,6 +104,13 @@ private fun ChipBody(
} else {
dimensionResource(id = R.dimen.ongoing_activity_chip_min_text_width) + chipSidePadding
}
+
+ val outline = model.colors.outline(context)
+ val outlineWidth = dimensionResource(R.dimen.ongoing_activity_chip_outline_width)
+
+ val shape =
+ RoundedCornerShape(dimensionResource(id = R.dimen.ongoing_activity_chip_corner_radius))
+
// Use a Box with `fillMaxHeight` to create a larger click surface for the chip. The visible
// height of the chip is determined by the height of the background of the Row below.
Box(
@@ -121,12 +129,7 @@ private fun ChipBody(
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
modifier =
- Modifier.clip(
- RoundedCornerShape(
- dimensionResource(id = R.dimen.ongoing_activity_chip_corner_radius)
- )
- )
- .height(dimensionResource(R.dimen.ongoing_appops_chip_height))
+ Modifier.height(dimensionResource(R.dimen.ongoing_appops_chip_height))
.thenIf(isClickable) { Modifier.widthIn(min = minWidth) }
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
@@ -136,7 +139,14 @@ private fun ChipBody(
}
}
}
- .background(Color(model.colors.background(context).defaultColor))
+ .background(Color(model.colors.background(context).defaultColor), shape = shape)
+ .thenIf(outline != null) {
+ Modifier.border(
+ width = outlineWidth,
+ color = Color(outline!!),
+ shape = shape,
+ )
+ }
.padding(
horizontal =
if (hasEmbeddedIcon) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt
index 25f90f9a0065..4954cb0a1b24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt
@@ -21,7 +21,6 @@ import android.content.res.ColorStateList
import androidx.annotation.ColorInt
import com.android.settingslib.Utils
import com.android.systemui.res.R
-import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel
/** Model representing how the chip in the status bar should be colored. */
sealed interface ColorsModel {
@@ -31,13 +30,38 @@ sealed interface ColorsModel {
/** The color for the text (and icon) on the chip. */
@ColorInt fun text(context: Context): Int
- /** The chip should match the theme's primary color. */
- data object Themed : ColorsModel {
+ /** The color to use for the chip outline, or null if the chip shouldn't have an outline. */
+ @ColorInt fun outline(context: Context): Int?
+
+ /** The chip should match the theme's primary accent color. */
+ // TODO(b/347717946): The chip's color isn't getting updated when the user switches theme, it
+ // only gets updated when a different configuration change happens, like a rotation.
+ data object AccentThemed : ColorsModel {
override fun background(context: Context): ColorStateList =
Utils.getColorAttr(context, com.android.internal.R.attr.colorAccent)
override fun text(context: Context) =
Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
+
+ override fun outline(context: Context) = null
+ }
+
+ /** The chip should match the system theme main color. */
+ // TODO(b/347717946): The chip's color isn't getting updated when the user switches theme, it
+ // only gets updated when a different configuration change happens, like a rotation.
+ data object SystemThemed : ColorsModel {
+ override fun background(context: Context): ColorStateList =
+ ColorStateList.valueOf(
+ context.getColor(com.android.internal.R.color.materialColorSurfaceDim)
+ )
+
+ override fun text(context: Context) =
+ context.getColor(com.android.internal.R.color.materialColorOnSurface)
+
+ override fun outline(context: Context) =
+ // Outline is required on the SystemThemed chip to guarantee the chip doesn't completely
+ // blend in with the background.
+ context.getColor(com.android.internal.R.color.materialColorOutlineVariant)
}
/** The chip should have the given background color and primary text color. */
@@ -46,6 +70,8 @@ sealed interface ColorsModel {
ColorStateList.valueOf(backgroundColorInt)
override fun text(context: Context): Int = primaryTextColorInt
+
+ override fun outline(context: Context) = null
}
/** The chip should have a red background with white text. */
@@ -55,15 +81,7 @@ sealed interface ColorsModel {
}
override fun text(context: Context) = context.getColor(android.R.color.white)
- }
- companion object {
- /** Converts the promoted notification colors to a [Custom] colors model. */
- fun PromotedNotificationContentModel.toCustomColorsModel(): Custom {
- return Custom(
- backgroundColorInt = this.colors.backgroundColor,
- primaryTextColorInt = this.colors.primaryTextColor,
- )
- }
+ override fun outline(context: Context) = null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelper.kt
index 52495eb55436..c19b144b7f42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/view/ChipTextTruncationHelper.kt
@@ -51,9 +51,8 @@ class ChipTextTruncationHelper(private val view: View) {
}
/**
- * Returns true if this view should show the text because there's enough room for a substantial
- * amount of text, and returns false if this view should hide the text because the text is much
- * too long.
+ * Returns true if this view should show the text because there's enough room for all the text,
+ * and returns false if this view should hide the text because not all of it fits.
*
* @param desiredTextWidthPx should be calculated by having the view measure itself with
* [unlimitedWidthMeasureSpec] and then sending its `measuredWidth` to this method. (This
@@ -82,9 +81,8 @@ class ChipTextTruncationHelper(private val view: View) {
enforcedTextWidth = maxWidthBasedOnDimension
}
- // Only show the text if at least 50% of it can show. (Assume that if < 50% of the text will
- // be visible, the text will be more confusing than helpful.)
- return desiredTextWidthPx <= enforcedTextWidth * 2
+ // Only show the text if all of it can show
+ return desiredTextWidthPx <= enforcedTextWidth
}
private fun fetchMaxWidth() =