TabRow
Composable Component
TV-Material Design Horizontal TabRow
Android
@Composable
fun TabRow(
selectedTabIndex: Int,
modifier: Modifier = Modifier,
containerColor: Color = TabRowDefaults.ContainerColor,
contentColor: Color = TabRowDefaults.contentColor(),
separator: @Composable () -> Unit = { TabRowDefaults.TabSeparator() },
indicator: @Composable (tabPositions: List<DpRect>, doesTabRowHaveFocus: Boolean) -> Unit =
@Composable { tabPositions, doesTabRowHaveFocus ->
tabPositions.getOrNull(selectedTabIndex)?.let { currentTabPosition ->
TabRowDefaults.PillIndicator(
currentTabPosition = currentTabPosition,
doesTabRowHaveFocus = doesTabRowHaveFocus
)
}
},
tabs: @Composable TabRowScope.() -> Unit
)
Parameters
selectedTabIndex | the index of the currently selected tab |
modifier | the Modifier to be applied to this tab row |
containerColor | the color used for the background of this tab row |
contentColor | the primary color used in the tabs |
separator | use this composable to add a separator between the tabs |
indicator | used to indicate which tab is currently selected and/or focused. This lambda provides 2 values: |
tabs | a composable which will render all the tabs |
Code Examples
OnClickNavigation
/** Tab changes onClick instead of onFocus */
@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable
fun OnClickNavigation() {
val bgColors =
listOf(
Color(0x6a, 0x16, 0x16),
Color(0x6a, 0x40, 0x16),
Color(0x6a, 0x6a, 0x16),
Color(0x40, 0x6a, 0x16),
)
var focusedTabIndex by remember { mutableStateOf(0) }
var activeTabIndex by remember { mutableStateOf(focusedTabIndex) }
Box(modifier = Modifier.fillMaxSize().background(bgColors[activeTabIndex])) {
TabRow(
selectedTabIndex = focusedTabIndex,
indicator = { tabPositions, doesTabRowHaveFocus ->
// FocusedTab's indicator
TabRowDefaults.PillIndicator(
currentTabPosition = tabPositions[focusedTabIndex],
activeColor = Color.Blue.copy(alpha = 0.4f),
inactiveColor = Color.Transparent,
doesTabRowHaveFocus = doesTabRowHaveFocus,
)
// SelectedTab's indicator
TabRowDefaults.PillIndicator(
currentTabPosition = tabPositions[activeTabIndex],
doesTabRowHaveFocus = doesTabRowHaveFocus,
)
},
modifier = Modifier.focusRestorer()
) {
repeat(bgColors.size) {
key(it) {
Tab(
selected = activeTabIndex == it,
onFocus = { focusedTabIndex = it },
onClick = {
focusedTabIndex = it
activeTabIndex = it
}
) {
Text(
text = "Tab ${it + 1}",
fontSize = 12.sp,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp)
)
}
}
}
}
}
}
PillIndicatorTabRow
/** Tab row with a Pill indicator */
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PillIndicatorTabRow() {
val tabs = listOf("Tab 1", "Tab 2", "Tab 3")
var selectedTabIndex by remember { mutableStateOf(0) }
TabRow(selectedTabIndex = selectedTabIndex, modifier = Modifier.focusRestorer()) {
tabs.forEachIndexed { index, tab ->
key(index) {
Tab(
selected = index == selectedTabIndex,
onFocus = { selectedTabIndex = index },
) {
Text(
text = tab,
fontSize = 12.sp,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp)
)
}
}
}
}
}
TabRowWithDebounce
/** Tab row with delay between tab changes */
@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable
fun TabRowWithDebounce() {
val tabs = listOf("Tab 1", "Tab 2", "Tab 3")
var selectedTabIndex by remember { mutableStateOf(0) }
// This index will be used to show a panel
var tabPanelIndex by remember { mutableStateOf(selectedTabIndex) }
// Change the tab-panel only after some delay
LaunchedEffect(selectedTabIndex) {
delay(250.microseconds)
tabPanelIndex = selectedTabIndex
}
TabRow(selectedTabIndex = selectedTabIndex, modifier = Modifier.focusRestorer()) {
tabs.forEachIndexed { index, tab ->
key(index) {
Tab(
selected = index == selectedTabIndex,
onFocus = { selectedTabIndex = index },
) {
Text(
text = tab,
fontSize = 12.sp,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp)
)
}
}
}
}
}
UnderlinedIndicatorTabRow
/** Tab row with an Underlined indicator */
@OptIn(ExperimentalTvMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable
fun UnderlinedIndicatorTabRow() {
val tabs = listOf("Tab 1", "Tab 2", "Tab 3")
var selectedTabIndex by remember { mutableStateOf(0) }
TabRow(
selectedTabIndex = selectedTabIndex,
indicator = { tabPositions, doesTabRowHaveFocus ->
TabRowDefaults.UnderlinedIndicator(
currentTabPosition = tabPositions[selectedTabIndex],
doesTabRowHaveFocus = doesTabRowHaveFocus,
)
},
modifier = Modifier.focusRestorer()
) {
tabs.forEachIndexed { index, tab ->
key(index) {
Tab(
selected = index == selectedTabIndex,
onFocus = { selectedTabIndex = index },
colors = TabDefaults.underlinedIndicatorTabColors(),
) {
Text(
text = tab,
fontSize = 12.sp,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp)
)
}
}
}
}
}
Create your own Component Library
Material Components are meant to be used as is and they do not allow customizations. To build your own Jetpack Compose component library use Compose Unstyled