Skip to content

Commit 3d67d98

Browse files
wcshiGerrit Code Review
authored andcommitted
Merge "Update text only tabs to match latest material.io spec. Currently they are baseline aligned, they should be vertically center aligned." into androidx-main
2 parents f344497 + b32aea4 commit 3d67d98

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)