Skip to content

Commit b32aea4

Browse files
committed
Update text only tabs to match latest material.io spec.
Currently they are baseline aligned, they should be vertically center aligned. Bug: 180595861 Test: TabTest, TabScreenshotTest Change-Id: Ifc7a1339fda59821c7c19f0a1fd9a724cfa34829
1 parent acd69e0 commit b32aea4

File tree

2 files changed

+16
-66
lines changed
  • compose/material/material/src
    • androidAndroidTest/kotlin/androidx/compose/material
    • commonMain/kotlin/androidx/compose/material

2 files changed

+16
-66
lines changed

compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/TabTest.kt

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ class TabTest {
290290
}
291291

292292
@Test
293-
fun singleLineTab_textBaseline() {
293+
fun singleLineTab_textPosition() {
294294
rule.setMaterialContent {
295295
var state by remember { mutableStateOf(0) }
296296
val titles = listOf("TAB")
@@ -313,19 +313,11 @@ class TabTest {
313313
}
314314
}
315315

316-
val expectedBaseline = 18.dp
317-
val indicatorHeight = 2.dp
318-
val expectedBaselineDistance = expectedBaseline + indicatorHeight
319-
320316
val tabRowBounds = rule.onNodeWithTag("tabRow").getUnclippedBoundsInRoot()
321317
val textBounds =
322318
rule.onNodeWithTag("text", useUnmergedTree = true).getUnclippedBoundsInRoot()
323-
val textBaselinePos =
324-
rule.onNodeWithTag("text", useUnmergedTree = true).getLastBaselinePosition()
325-
326-
val baselinePositionY = textBounds.top + textBaselinePos
327-
val expectedPositionY = tabRowBounds.height - expectedBaselineDistance
328-
baselinePositionY.assertIsEqualTo(expectedPositionY, "baseline y-position")
319+
val expectedPositionY = (tabRowBounds.height - textBounds.height) / 2
320+
textBounds.top.assertIsEqualTo(expectedPositionY, "text bounds top y-position")
329321
}
330322

331323
@Test
@@ -369,7 +361,7 @@ class TabTest {
369361
}
370362

371363
@Test
372-
fun twoLineTab_textBaseline() {
364+
fun twoLineTab_textPosition() {
373365
rule.setMaterialContent {
374366
var state by remember { mutableStateOf(0) }
375367
val titles = listOf("Two line \n text")
@@ -392,20 +384,12 @@ class TabTest {
392384
}
393385
}
394386

395-
val expectedBaseline = 10.dp
396-
val indicatorHeight = 2.dp
397-
398387
val tabRowBounds = rule.onNodeWithTag("tabRow").getUnclippedBoundsInRoot()
399388
val textBounds =
400389
rule.onNodeWithTag("text", useUnmergedTree = true).getUnclippedBoundsInRoot()
401-
val textBaselinePos =
402-
rule.onNodeWithTag("text", useUnmergedTree = true).getLastBaselinePosition()
403390

404-
val expectedBaselineDistance = expectedBaseline + indicatorHeight
405-
406-
val baselinePositionY = textBounds.top + textBaselinePos
407-
val expectedPositionY = (tabRowBounds.height - expectedBaselineDistance)
408-
baselinePositionY.assertIsEqualTo(expectedPositionY, "baseline y-position")
391+
val expectedPositionY = (tabRowBounds.height - textBounds.height) / 2
392+
textBounds.top.assertIsEqualTo(expectedPositionY, "text bounds top y-position")
409393
}
410394

411395
@OptIn(ExperimentalMaterialApi::class)

compose/material/material/src/commonMain/kotlin/androidx/compose/material/Tab.kt

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -349,55 +349,25 @@ private fun TabBaselineLayout(
349349
firstBaseline = firstBaseline!!,
350350
lastBaseline = lastBaseline!!
351351
)
352-
textPlaceable != null -> placeText(
353-
density = this@Layout,
354-
textPlaceable = textPlaceable,
355-
tabHeight = tabHeight,
356-
firstBaseline = firstBaseline!!,
357-
lastBaseline = lastBaseline!!
358-
)
359-
iconPlaceable != null -> placeIcon(iconPlaceable, tabHeight)
360-
else -> {}
352+
textPlaceable != null -> placeTextOrIcon(textPlaceable, tabHeight)
353+
iconPlaceable != null -> placeTextOrIcon(iconPlaceable, tabHeight)
354+
else -> {
355+
}
361356
}
362357
}
363358
}
364359
}
365360

366361
/**
367-
* Places the provided [iconPlaceable] in the vertical center of the provided [tabHeight].
362+
* Places the provided [textOrIconPlaceable] in the vertical center of the provided
363+
* [tabHeight].
368364
*/
369-
private fun Placeable.PlacementScope.placeIcon(
370-
iconPlaceable: Placeable,
365+
private fun Placeable.PlacementScope.placeTextOrIcon(
366+
textOrIconPlaceable: Placeable,
371367
tabHeight: Int
372368
) {
373-
val iconY = (tabHeight - iconPlaceable.height) / 2
374-
iconPlaceable.placeRelative(0, iconY)
375-
}
376-
377-
/**
378-
* Places the provided [textPlaceable] offset from the bottom of the tab using the correct
379-
* baseline offset.
380-
*/
381-
private fun Placeable.PlacementScope.placeText(
382-
density: Density,
383-
textPlaceable: Placeable,
384-
tabHeight: Int,
385-
firstBaseline: Int,
386-
lastBaseline: Int
387-
) {
388-
val baselineOffset = if (firstBaseline == lastBaseline) {
389-
SingleLineTextBaseline
390-
} else {
391-
DoubleLineTextBaseline
392-
}
393-
394-
// Total offset between the last text baseline and the bottom of the Tab layout
395-
val totalOffset = with(density) {
396-
baselineOffset.roundToPx() + TabRowDefaults.IndicatorHeight.roundToPx()
397-
}
398-
399-
val textPlaceableY = tabHeight - lastBaseline - totalOffset
400-
textPlaceable.placeRelative(0, textPlaceableY)
369+
val contentY = (tabHeight - textOrIconPlaceable.height) / 2
370+
textOrIconPlaceable.placeRelative(0, contentY)
401371
}
402372

403373
/**
@@ -452,14 +422,10 @@ private const val TabFadeOutAnimationDuration = 100
452422
// The horizontal padding on the left and right of text
453423
private val HorizontalTextPadding = 16.dp
454424

455-
// Distance from the top of the indicator to the text baseline when there is one line of text
456-
private val SingleLineTextBaseline = 18.dp
457425
// Distance from the top of the indicator to the text baseline when there is one line of text and an
458426
// icon
459427
private val SingleLineTextBaselineWithIcon = 14.dp
460428
// Distance from the top of the indicator to the last text baseline when there are two lines of text
461-
private val DoubleLineTextBaseline = 10.dp
462-
// Distance from the top of the indicator to the last text baseline when there are two lines of text
463429
// and an icon
464430
private val DoubleLineTextBaselineWithIcon = 6.dp
465431
// Distance from the first text baseline to the bottom of the icon in a combined tab

0 commit comments

Comments
 (0)