Loading packages/SystemUI/pods/src/com/android/systemui/notifications/ui/composable/component/PrioritizedRow.kt +99 −35 Original line number Diff line number Diff line Loading @@ -136,6 +136,10 @@ public fun PrioritizedRow( init { check(hideWidth <= reducedWidth) { "hideWidth must be smaller than reducedWidth" } } fun shrinkable(): Boolean = !isSeparator && (reducedWidth < currentWidth) fun hideable(): Boolean = canHide && isVisible && (hideWidth < currentWidth) } fun List<LayoutCandidate>.previousVisibleChild(index: Int): LayoutCandidate? { Loading Loading @@ -199,33 +203,89 @@ public fun PrioritizedRow( // SHRINK: The content doesn't fit, start shrinking elements down to their reduced width // based on priority for (i in sortedContent.indices) { val shrinkCandidate = sortedContent[i] var i = 0 while (i < sortedContent.size) { if (!sortedContent[i].shrinkable()) { i++ continue } // Take all candidates with the same importance, and shrink them simultaneously val importance = sortedContent[i].importance var shrinkableCnt = 1 var lastShrinkableIdx = i for (j in i + 1 until sortedContent.size) { if (sortedContent[j].importance != importance) break if (sortedContent[j].shrinkable()) { lastShrinkableIdx = j shrinkableCnt++ } } var remainingShrinkables = shrinkableCnt for (j in i..lastShrinkableIdx) { val shrinkCandidate = sortedContent[j] if (!shrinkCandidate.shrinkable()) continue // Distribute the space needed across all remaining candidates val wantedSpace = (overflow / remainingShrinkables) + minOf(1, overflow % remainingShrinkables) remainingShrinkables-- // TODO: b/431222735 - Shrink elements with the same importance simultaneously. val shrinkableSpace = shrinkCandidate.currentWidth - shrinkCandidate.reducedWidth if (shrinkableSpace <= 0) continue val shrinkAmount = minOf(overflow, shrinkableSpace) val shrinkableSpace = shrinkCandidate.currentWidth - shrinkCandidate.reducedWidth val shrinkAmount = minOf(wantedSpace, shrinkableSpace, overflow) shrinkCandidate.currentWidth -= shrinkAmount overflow -= shrinkAmount } if (overflow <= 0) break i = lastShrinkableIdx + 1 } // HIDE: Content still doesn't fit, so we need to shrink elements further, and maybe // even hide them. var somethingWasHidden = false if (overflow > 0) { for (i in sortedContent.indices) { val hideCandidate = sortedContent[i] if (!hideCandidate.canHide || !hideCandidate.isVisible) continue i = 0 while (i < sortedContent.size) { if (!sortedContent[i].hideable()) { i++ continue } // Take all hideable candidates with the same importance, and try to shrink them // proportionally before hiding them val importance = sortedContent[i].importance var hideableCnt = 1 var lastHideableIdx = i for (j in i + 1 until sortedContent.size) { if (sortedContent[j].importance != importance) break if (sortedContent[j].hideable()) { lastHideableIdx = j hideableCnt++ } } var remainingHideables = hideableCnt for (j in i..lastHideableIdx) { val hideCandidate = sortedContent[j] if (!hideCandidate.hideable()) continue // Distribute the space needed across all remaining candidates val wantedSpace = (overflow / remainingHideables) + minOf(1, overflow % remainingHideables) remainingHideables-- // One last attempt to shrink this element further val shrinkableSpace = hideCandidate.currentWidth - hideCandidate.hideWidth if (shrinkableSpace >= overflow) { hideCandidate.currentWidth -= overflow overflow = 0 break if (shrinkableSpace >= wantedSpace) { hideCandidate.currentWidth -= wantedSpace overflow -= wantedSpace continue } // Shrinking wouldn't be enough, so let's hide it Loading @@ -250,6 +310,10 @@ public fun PrioritizedRow( overflow -= spaceToReclaim if (overflow <= 0) break } if (overflow <= 0) break i = lastHideableIdx + 1 } } // REGROW: If hiding items created extra space, give it back to visible shrunk items. Loading packages/SystemUI/pods/src/com/android/systemui/notifications/ui/composable/component/Text.kt +7 −3 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ internal fun ExpandedText(content: String, maxLines: Int, modifier: Modifier = M @Composable internal fun TopLineText( modifier: Modifier = Modifier, title: String? = null, appNameText: String? = null, headerTextSecondary: String? = null, headerText: String? = null, Loading @@ -87,9 +88,12 @@ internal fun TopLineText( } } // TODO: b/431222735 - Add a title with a separate style. if (appNameText != null) { if (title != null) { isFirstElement = false Title(title, Modifier.shrinkable(importance = 3, minWidth = reducedWidth)) } if (appNameText != null) { maybeAddSeparator() TopLineComponentText( text = appNameText, modifier = Modifier.shrinkable(importance = 1, minWidth = reducedWidth), Loading @@ -101,7 +105,7 @@ internal fun TopLineText( text = headerTextSecondary, modifier = Modifier.hideable( importance = 4, importance = 3, reducedWidth = reducedWidth, hideWidth = hideWidth, ), Loading packages/SystemUI/pods/src/com/android/systemui/notifications/ui/composable/content/NotificationContent.kt +16 −2 Original line number Diff line number Diff line Loading @@ -42,7 +42,19 @@ public fun NotificationContent(viewModel: NotificationViewModel, modifier: Modif if (!viewModel.isExpanded) { NotificationRow( viewModel, firstLine = { Title(viewModel.title) }, firstLine = { TopLineText( modifier = Modifier.padding(vertical = 2.dp), title = viewModel.title, // When collapsed, app name is only shown when there is no title appNameText = if (viewModel.title == null) viewModel.appName else null, headerTextSecondary = viewModel.headerTextSecondary, headerText = viewModel.headerText, // TODO: b/431222735 - Implement time/chronometer logic. timeText = "now", verificationText = viewModel.verificationText, ) }, secondLine = { viewModel.text?.let { CollapsedText(it) } }, modifier, ) Loading @@ -60,7 +72,9 @@ public fun NotificationContent(viewModel: NotificationViewModel, modifier: Modif verificationText = viewModel.verificationText, ) }, secondLine = { Title(viewModel.title) }, // TODO: b/431222735 - Consider showing the expanded text here when there is no title. // this would require a mechanism for getting the text to wrap around the large icon. secondLine = { Title(viewModel.title ?: "") }, modifier, ) { viewModel.text?.let { ExpandedText(it, maxLines = viewModel.maxLinesWhenExpanded) } Loading packages/SystemUI/pods/src/com/android/systemui/notifications/ui/viewmodel/NotificationViewModel.kt +1 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ public interface NotificationViewModel { // TODO: b/431222735 - Make this nullable once we implement the top line fields. /** The title of the notification, emphasized in the content. */ public val title: String public val title: String? /** The content text of the notification, shown below the title. */ public val text: String? Loading packages/SystemUI/tests/src/com/android/systemui/notifications/ui/composable/component/PrioritizedRowTest.kt +48 −39 Original line number Diff line number Diff line Loading @@ -95,6 +95,36 @@ class PrioritizedRowTest : SysuiTestCase() { rule.onNodeWithTag("row").assertWidthIsEqualTo(420.dp) } @Test fun width320dp_sameImportance_allShrinkablesShrink() { rule.setContent { CompositionLocalProvider(LocalDensity provides density) { PlatformTheme { PrioritizedRow(modifier = Modifier.width(320.dp).testTag("row")) { // All children have the same importance (everything else stays the same) TestContent(forceSameImportance = true) } } } } rule.onNodeWithTag("icon0").assertIsDisplayedWithWidth(iconWidth) rule.onNodeWithTag("spacer0").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithTag("icon1").assertIsDisplayedWithWidth(iconWidth) rule.onNodeWithTag("spacer1").assertIsDisplayedWithWidth(separatorWidth) // The required space is distributed across all 3 shrinkables, but they can't go below // reducedWidth. rule.onNodeWithText("High Importance").assertIsDisplayedWithWidth(reducedWidth) rule.onNodeWithTag("dot0").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("Medium (Shrinkable)").assertIsDisplayedWithWidth(57.5.dp) rule.onNodeWithTag("dot1").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithTag("Low (Hideable)").assertIsDisplayedWithWidth(64.5.dp) rule.onNodeWithTag("spacer2").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("FIXED").assertIsDisplayedWithWidth(fixedWidth) rule.onNodeWithTag("row").assertWidthIsEqualTo(320.dp) } @Test fun width400dp_lowPriorityRowShrinks() { rule.setContent { Loading Loading @@ -183,21 +213,21 @@ class PrioritizedRowTest : SysuiTestCase() { } @Test fun width290dp_firstIconShrinks() { fun width280dp_startIconsShrink() { rule.setContent { CompositionLocalProvider(LocalDensity provides density) { PlatformTheme { PrioritizedRow(modifier = Modifier.width(290.dp).testTag("row")) { PrioritizedRow(modifier = Modifier.width(280.dp).testTag("row")) { TestContent() } } } } // First icon starts shrinking before being hidden rule.onNodeWithTag("icon0").assertIsDisplayedWithWidth(16.dp) // Start icons have the same importance, so they both start shrinking rule.onNodeWithTag("icon0").assertIsDisplayedWithWidth(15.dp) rule.onNodeWithTag("spacer0").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithTag("icon1").assertIsDisplayedWithWidth(iconWidth) rule.onNodeWithTag("icon1").assertIsDisplayedWithWidth(15.dp) rule.onNodeWithTag("spacer1").assertIsDisplayedWithWidth(separatorWidth) // High priority text doesn't shrink beyond reducedWidth rule.onNodeWithText("High Importance").assertIsDisplayedWithWidth(reducedWidth) Loading @@ -209,36 +239,7 @@ class PrioritizedRowTest : SysuiTestCase() { rule.onNodeWithTag("spacer2").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("FIXED").assertIsDisplayedWithWidth(fixedWidth) rule.onNodeWithTag("row").assertWidthIsEqualTo(290.dp) } @Test fun width240dp_firstIconHides() { rule.setContent { CompositionLocalProvider(LocalDensity provides density) { PlatformTheme { PrioritizedRow(modifier = Modifier.width(240.dp).testTag("row")) { TestContent() } } } } // First icon and corresponding spacer disappear rule.onNodeWithTag("icon0").assertIsNotDisplayed() rule.onNodeWithTag("spacer0").assertIsNotDisplayed() // Second icon starts shrinking rule.onNodeWithTag("icon1").assertIsDisplayedWithWidth(5.dp) rule.onNodeWithTag("spacer1").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("High Importance").assertIsDisplayedWithWidth(reducedWidth) rule.onNodeWithTag("dot0").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("Medium (Shrinkable)").assertIsDisplayedWithWidth(reducedWidth) rule.onNodeWithTag("dot1").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithTag("Low (Hideable)").assertIsDisplayedWithWidth(reducedWidth) rule.onNodeWithTag("spacer2").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("FIXED").assertIsDisplayedWithWidth(fixedWidth) rule.onNodeWithTag("row").assertWidthIsEqualTo(240.dp) rule.onNodeWithTag("row").assertWidthIsEqualTo(280.dp) } @Test Loading Loading @@ -329,7 +330,7 @@ class PrioritizedRowTest : SysuiTestCase() { // Note: This composable is forked in the Compose Gallery app for interactive, manual testing. @Composable private fun PrioritizedRowScope.TestContent() { private fun PrioritizedRowScope.TestContent(forceSameImportance: Boolean = false) { // Note: This font family & size (together with the fixed density configuration) means that // each character in a text composable will have a width of 5dp. val fontFamily = FontFamily.Monospace Loading @@ -355,7 +356,11 @@ class PrioritizedRowTest : SysuiTestCase() { // This text will be the last to shrink Text( text = "High Importance", modifier = Modifier.shrinkable(importance = 3, minWidth = reducedWidth), modifier = Modifier.shrinkable( importance = if (forceSameImportance) 0 else 3, minWidth = reducedWidth, ), maxLines = 1, overflow = TextOverflow.Ellipsis, fontFamily = fontFamily, Loading @@ -371,7 +376,11 @@ class PrioritizedRowTest : SysuiTestCase() { // This text will shrink to its minWidth Text( text = "Medium (Shrinkable)", modifier = Modifier.shrinkable(importance = 2, minWidth = reducedWidth), modifier = Modifier.shrinkable( importance = if (forceSameImportance) 0 else 2, minWidth = reducedWidth, ), maxLines = 1, overflow = TextOverflow.Ellipsis, fontFamily = fontFamily, Loading @@ -388,7 +397,7 @@ class PrioritizedRowTest : SysuiTestCase() { Row( modifier = Modifier.hideable( importance = 1, importance = if (forceSameImportance) 0 else 1, reducedWidth = reducedWidth, hideWidth = hideWidth, ) Loading Loading
packages/SystemUI/pods/src/com/android/systemui/notifications/ui/composable/component/PrioritizedRow.kt +99 −35 Original line number Diff line number Diff line Loading @@ -136,6 +136,10 @@ public fun PrioritizedRow( init { check(hideWidth <= reducedWidth) { "hideWidth must be smaller than reducedWidth" } } fun shrinkable(): Boolean = !isSeparator && (reducedWidth < currentWidth) fun hideable(): Boolean = canHide && isVisible && (hideWidth < currentWidth) } fun List<LayoutCandidate>.previousVisibleChild(index: Int): LayoutCandidate? { Loading Loading @@ -199,33 +203,89 @@ public fun PrioritizedRow( // SHRINK: The content doesn't fit, start shrinking elements down to their reduced width // based on priority for (i in sortedContent.indices) { val shrinkCandidate = sortedContent[i] var i = 0 while (i < sortedContent.size) { if (!sortedContent[i].shrinkable()) { i++ continue } // Take all candidates with the same importance, and shrink them simultaneously val importance = sortedContent[i].importance var shrinkableCnt = 1 var lastShrinkableIdx = i for (j in i + 1 until sortedContent.size) { if (sortedContent[j].importance != importance) break if (sortedContent[j].shrinkable()) { lastShrinkableIdx = j shrinkableCnt++ } } var remainingShrinkables = shrinkableCnt for (j in i..lastShrinkableIdx) { val shrinkCandidate = sortedContent[j] if (!shrinkCandidate.shrinkable()) continue // Distribute the space needed across all remaining candidates val wantedSpace = (overflow / remainingShrinkables) + minOf(1, overflow % remainingShrinkables) remainingShrinkables-- // TODO: b/431222735 - Shrink elements with the same importance simultaneously. val shrinkableSpace = shrinkCandidate.currentWidth - shrinkCandidate.reducedWidth if (shrinkableSpace <= 0) continue val shrinkAmount = minOf(overflow, shrinkableSpace) val shrinkableSpace = shrinkCandidate.currentWidth - shrinkCandidate.reducedWidth val shrinkAmount = minOf(wantedSpace, shrinkableSpace, overflow) shrinkCandidate.currentWidth -= shrinkAmount overflow -= shrinkAmount } if (overflow <= 0) break i = lastShrinkableIdx + 1 } // HIDE: Content still doesn't fit, so we need to shrink elements further, and maybe // even hide them. var somethingWasHidden = false if (overflow > 0) { for (i in sortedContent.indices) { val hideCandidate = sortedContent[i] if (!hideCandidate.canHide || !hideCandidate.isVisible) continue i = 0 while (i < sortedContent.size) { if (!sortedContent[i].hideable()) { i++ continue } // Take all hideable candidates with the same importance, and try to shrink them // proportionally before hiding them val importance = sortedContent[i].importance var hideableCnt = 1 var lastHideableIdx = i for (j in i + 1 until sortedContent.size) { if (sortedContent[j].importance != importance) break if (sortedContent[j].hideable()) { lastHideableIdx = j hideableCnt++ } } var remainingHideables = hideableCnt for (j in i..lastHideableIdx) { val hideCandidate = sortedContent[j] if (!hideCandidate.hideable()) continue // Distribute the space needed across all remaining candidates val wantedSpace = (overflow / remainingHideables) + minOf(1, overflow % remainingHideables) remainingHideables-- // One last attempt to shrink this element further val shrinkableSpace = hideCandidate.currentWidth - hideCandidate.hideWidth if (shrinkableSpace >= overflow) { hideCandidate.currentWidth -= overflow overflow = 0 break if (shrinkableSpace >= wantedSpace) { hideCandidate.currentWidth -= wantedSpace overflow -= wantedSpace continue } // Shrinking wouldn't be enough, so let's hide it Loading @@ -250,6 +310,10 @@ public fun PrioritizedRow( overflow -= spaceToReclaim if (overflow <= 0) break } if (overflow <= 0) break i = lastHideableIdx + 1 } } // REGROW: If hiding items created extra space, give it back to visible shrunk items. Loading
packages/SystemUI/pods/src/com/android/systemui/notifications/ui/composable/component/Text.kt +7 −3 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ internal fun ExpandedText(content: String, maxLines: Int, modifier: Modifier = M @Composable internal fun TopLineText( modifier: Modifier = Modifier, title: String? = null, appNameText: String? = null, headerTextSecondary: String? = null, headerText: String? = null, Loading @@ -87,9 +88,12 @@ internal fun TopLineText( } } // TODO: b/431222735 - Add a title with a separate style. if (appNameText != null) { if (title != null) { isFirstElement = false Title(title, Modifier.shrinkable(importance = 3, minWidth = reducedWidth)) } if (appNameText != null) { maybeAddSeparator() TopLineComponentText( text = appNameText, modifier = Modifier.shrinkable(importance = 1, minWidth = reducedWidth), Loading @@ -101,7 +105,7 @@ internal fun TopLineText( text = headerTextSecondary, modifier = Modifier.hideable( importance = 4, importance = 3, reducedWidth = reducedWidth, hideWidth = hideWidth, ), Loading
packages/SystemUI/pods/src/com/android/systemui/notifications/ui/composable/content/NotificationContent.kt +16 −2 Original line number Diff line number Diff line Loading @@ -42,7 +42,19 @@ public fun NotificationContent(viewModel: NotificationViewModel, modifier: Modif if (!viewModel.isExpanded) { NotificationRow( viewModel, firstLine = { Title(viewModel.title) }, firstLine = { TopLineText( modifier = Modifier.padding(vertical = 2.dp), title = viewModel.title, // When collapsed, app name is only shown when there is no title appNameText = if (viewModel.title == null) viewModel.appName else null, headerTextSecondary = viewModel.headerTextSecondary, headerText = viewModel.headerText, // TODO: b/431222735 - Implement time/chronometer logic. timeText = "now", verificationText = viewModel.verificationText, ) }, secondLine = { viewModel.text?.let { CollapsedText(it) } }, modifier, ) Loading @@ -60,7 +72,9 @@ public fun NotificationContent(viewModel: NotificationViewModel, modifier: Modif verificationText = viewModel.verificationText, ) }, secondLine = { Title(viewModel.title) }, // TODO: b/431222735 - Consider showing the expanded text here when there is no title. // this would require a mechanism for getting the text to wrap around the large icon. secondLine = { Title(viewModel.title ?: "") }, modifier, ) { viewModel.text?.let { ExpandedText(it, maxLines = viewModel.maxLinesWhenExpanded) } Loading
packages/SystemUI/pods/src/com/android/systemui/notifications/ui/viewmodel/NotificationViewModel.kt +1 −1 Original line number Diff line number Diff line Loading @@ -33,7 +33,7 @@ public interface NotificationViewModel { // TODO: b/431222735 - Make this nullable once we implement the top line fields. /** The title of the notification, emphasized in the content. */ public val title: String public val title: String? /** The content text of the notification, shown below the title. */ public val text: String? Loading
packages/SystemUI/tests/src/com/android/systemui/notifications/ui/composable/component/PrioritizedRowTest.kt +48 −39 Original line number Diff line number Diff line Loading @@ -95,6 +95,36 @@ class PrioritizedRowTest : SysuiTestCase() { rule.onNodeWithTag("row").assertWidthIsEqualTo(420.dp) } @Test fun width320dp_sameImportance_allShrinkablesShrink() { rule.setContent { CompositionLocalProvider(LocalDensity provides density) { PlatformTheme { PrioritizedRow(modifier = Modifier.width(320.dp).testTag("row")) { // All children have the same importance (everything else stays the same) TestContent(forceSameImportance = true) } } } } rule.onNodeWithTag("icon0").assertIsDisplayedWithWidth(iconWidth) rule.onNodeWithTag("spacer0").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithTag("icon1").assertIsDisplayedWithWidth(iconWidth) rule.onNodeWithTag("spacer1").assertIsDisplayedWithWidth(separatorWidth) // The required space is distributed across all 3 shrinkables, but they can't go below // reducedWidth. rule.onNodeWithText("High Importance").assertIsDisplayedWithWidth(reducedWidth) rule.onNodeWithTag("dot0").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("Medium (Shrinkable)").assertIsDisplayedWithWidth(57.5.dp) rule.onNodeWithTag("dot1").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithTag("Low (Hideable)").assertIsDisplayedWithWidth(64.5.dp) rule.onNodeWithTag("spacer2").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("FIXED").assertIsDisplayedWithWidth(fixedWidth) rule.onNodeWithTag("row").assertWidthIsEqualTo(320.dp) } @Test fun width400dp_lowPriorityRowShrinks() { rule.setContent { Loading Loading @@ -183,21 +213,21 @@ class PrioritizedRowTest : SysuiTestCase() { } @Test fun width290dp_firstIconShrinks() { fun width280dp_startIconsShrink() { rule.setContent { CompositionLocalProvider(LocalDensity provides density) { PlatformTheme { PrioritizedRow(modifier = Modifier.width(290.dp).testTag("row")) { PrioritizedRow(modifier = Modifier.width(280.dp).testTag("row")) { TestContent() } } } } // First icon starts shrinking before being hidden rule.onNodeWithTag("icon0").assertIsDisplayedWithWidth(16.dp) // Start icons have the same importance, so they both start shrinking rule.onNodeWithTag("icon0").assertIsDisplayedWithWidth(15.dp) rule.onNodeWithTag("spacer0").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithTag("icon1").assertIsDisplayedWithWidth(iconWidth) rule.onNodeWithTag("icon1").assertIsDisplayedWithWidth(15.dp) rule.onNodeWithTag("spacer1").assertIsDisplayedWithWidth(separatorWidth) // High priority text doesn't shrink beyond reducedWidth rule.onNodeWithText("High Importance").assertIsDisplayedWithWidth(reducedWidth) Loading @@ -209,36 +239,7 @@ class PrioritizedRowTest : SysuiTestCase() { rule.onNodeWithTag("spacer2").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("FIXED").assertIsDisplayedWithWidth(fixedWidth) rule.onNodeWithTag("row").assertWidthIsEqualTo(290.dp) } @Test fun width240dp_firstIconHides() { rule.setContent { CompositionLocalProvider(LocalDensity provides density) { PlatformTheme { PrioritizedRow(modifier = Modifier.width(240.dp).testTag("row")) { TestContent() } } } } // First icon and corresponding spacer disappear rule.onNodeWithTag("icon0").assertIsNotDisplayed() rule.onNodeWithTag("spacer0").assertIsNotDisplayed() // Second icon starts shrinking rule.onNodeWithTag("icon1").assertIsDisplayedWithWidth(5.dp) rule.onNodeWithTag("spacer1").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("High Importance").assertIsDisplayedWithWidth(reducedWidth) rule.onNodeWithTag("dot0").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("Medium (Shrinkable)").assertIsDisplayedWithWidth(reducedWidth) rule.onNodeWithTag("dot1").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithTag("Low (Hideable)").assertIsDisplayedWithWidth(reducedWidth) rule.onNodeWithTag("spacer2").assertIsDisplayedWithWidth(separatorWidth) rule.onNodeWithText("FIXED").assertIsDisplayedWithWidth(fixedWidth) rule.onNodeWithTag("row").assertWidthIsEqualTo(240.dp) rule.onNodeWithTag("row").assertWidthIsEqualTo(280.dp) } @Test Loading Loading @@ -329,7 +330,7 @@ class PrioritizedRowTest : SysuiTestCase() { // Note: This composable is forked in the Compose Gallery app for interactive, manual testing. @Composable private fun PrioritizedRowScope.TestContent() { private fun PrioritizedRowScope.TestContent(forceSameImportance: Boolean = false) { // Note: This font family & size (together with the fixed density configuration) means that // each character in a text composable will have a width of 5dp. val fontFamily = FontFamily.Monospace Loading @@ -355,7 +356,11 @@ class PrioritizedRowTest : SysuiTestCase() { // This text will be the last to shrink Text( text = "High Importance", modifier = Modifier.shrinkable(importance = 3, minWidth = reducedWidth), modifier = Modifier.shrinkable( importance = if (forceSameImportance) 0 else 3, minWidth = reducedWidth, ), maxLines = 1, overflow = TextOverflow.Ellipsis, fontFamily = fontFamily, Loading @@ -371,7 +376,11 @@ class PrioritizedRowTest : SysuiTestCase() { // This text will shrink to its minWidth Text( text = "Medium (Shrinkable)", modifier = Modifier.shrinkable(importance = 2, minWidth = reducedWidth), modifier = Modifier.shrinkable( importance = if (forceSameImportance) 0 else 2, minWidth = reducedWidth, ), maxLines = 1, overflow = TextOverflow.Ellipsis, fontFamily = fontFamily, Loading @@ -388,7 +397,7 @@ class PrioritizedRowTest : SysuiTestCase() { Row( modifier = Modifier.hideable( importance = 1, importance = if (forceSameImportance) 0 else 1, reducedWidth = reducedWidth, hideWidth = hideWidth, ) Loading