跳转到内容

TabRow

TabRow 是 COUI 中的导航组件,完整复刻了 ColorOS 16 的分段按钮(COUISegmentButtonLayout)。提供了带轮廓(Contour)样式(带容器胶囊与滑动指示器)和标准样式(去掉容器底色的同款分段按钮)两种变体,适用于内容分类和导航场景。

引入

kotlin
import io.github.suqi8.coui.kmp.basic.TabRow // 标准样式(无外框)
import io.github.suqi8.coui.kmp.basic.TabRowWithContour // 带轮廓样式(分段按钮)

基本用法

标准样式

标准样式默认在透明背景上只绘制滑动胶囊指示器及其投影。

kotlin
val tabs = listOf("推荐", "关注", "热门", "精选")
var selectedTabIndex by remember { mutableStateOf(0) }

TabRow(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it }
)

带轮廓样式

带轮廓样式与 ColorOS 分段按钮一致:40dp 高的胶囊容器,四边 4dp 内缩的滑动指示器。分段宽度由文字自然宽度(至少 52dp)计算后铺满整行。

kotlin
val tabs = listOf("全部", "照片", "视频", "文档")
var selectedTabIndex by remember { mutableStateOf(0) }

TabRowWithContour(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it }
)

记住滚动位置

当标签在最小宽度下也放不下时,标签行会变为可滚动。

kotlin
val tabs = listOf("标签1", "标签2", "标签3", "标签4", "标签5")
var selectedTabIndex by remember { mutableStateOf(3) }
val tabListState = rememberLazyListState()

TabRowWithContour(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it },
    listState = tabListState,
)

属性

TabRow 属性

属性名类型说明默认值是否必须
tabsList<String>标签文本列表-
selectedTabIndexInt当前选中的标签索引-
onTabSelected(Int) -> Unit标签选中时的回调函数-
modifierModifier应用于标签行的修饰符Modifier
colorsTabRowColors标签行的颜色配置TabRowDefaults.tabRowColors(backgroundColor = Color.Transparent)
minWidthDp每个标签的最小宽度TabRowDefaults.TabRowMinWidth
maxWidthDp每个标签的最大宽度TabRowDefaults.TabRowMaxWidth
heightDp标签行的高度TabRowDefaults.TabRowHeight
cornerRadiusDp滑动指示器的圆角半径TabRowDefaults.TabRowCornerRadius
itemSpacingDp标签之间的间距0.dp
contentAlignmentAlignment标签内容的对齐方式Alignment.Center
listStateLazyListState?标签列表的外部滚动状态null
interactionSourceMutableInteractionSource?标签项的交互源null
indicationIndication?标签项的点击反馈效果null

TabRowWithContour 属性

属性名类型说明默认值是否必须
tabsList<String>标签文本列表-
selectedTabIndexInt当前选中的标签索引-
onTabSelected(Int) -> Unit标签选中时的回调函数-
modifierModifier应用于标签行的修饰符Modifier
colorsTabRowColors标签行的颜色配置TabRowDefaults.tabRowColors()
minWidthDp每个标签的最小宽度TabRowDefaults.TabRowWithContourMinWidth
maxWidthDp每个标签的最大宽度TabRowDefaults.TabRowWithContourMaxWidth
heightDp标签行的高度TabRowDefaults.TabRowWithContourHeight
cornerRadiusDp滑动指示器的圆角半径TabRowDefaults.TabRowWithContourCornerRadius
contourPaddingDp容器与滑动指示器间的内缩TabRowDefaults.TabRowWithContourPadding
itemSpacingDp标签之间的间距0.dp
contentAlignmentAlignment标签内容的对齐方式Alignment.Center
listStateLazyListState?标签列表的外部滚动状态null
interactionSourceMutableInteractionSource?标签项的交互源null
indicationIndication?标签项的点击反馈效果null

TabRowDefaults 对象

TabRowDefaults 对象提供了 TabRow 组件的默认配置。

常量

常量名类型说明
TabRowHeightDp40.dp标准样式的默认高度
TabRowWithContourHeightDp40.dp带轮廓样式的默认高度
TabRowWithContourTinyHeightDp32.dpCOUI SegmentButton.Tiny 样式的高度
TabRowCornerRadiusDp20.dp标准样式滑块的默认圆角半径(胶囊形)
TabRowWithContourCornerRadiusDp16.dp带轮廓样式滑块的默认圆角半径(胶囊形)
TabRowWithContourTinyCornerRadiusDp14.dpSegmentButton.Tiny 样式滑块的圆角半径
TabRowWithContourPaddingDp4.dp容器与滑块之间的默认内缩
TabRowWithContourTinyPaddingDp2.dpSegmentButton.Tiny 样式的容器内缩
TabRowMinWidthDp52.dp标准样式的每个标签最小宽度
TabRowWithContourMinWidthDp52.dp带轮廓样式的每个标签最小宽度
TabRowMaxWidthDpDp.Infinity标准样式的每个标签最大宽度(无上限,标签铺满整行)
TabRowWithContourMaxWidthDpDp.Infinity带轮廓样式的每个标签最大宽度(无上限,标签铺满整行)

方法

方法名类型说明
tabRowColors()TabRowColors创建标签行的默认颜色配置

TabRowColors 类

属性名类型说明
backgroundColorColor容器的背景色
contentColorColor标签的默认内容色
selectedBackgroundColorColor滑动指示器的颜色
selectedContentColorColor选中标签的内容色

进阶用法

自定义颜色

kotlin
val tabs = listOf("最新", "热门", "关注")
var selectedTabIndex by remember { mutableStateOf(0) }

TabRow(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it },
    colors = TabRowDefaults.tabRowColors(
        backgroundColor = Color.LightGray.copy(alpha = 0.5f),
        contentColor = Color.Gray,
        selectedBackgroundColor = COUITheme.colorScheme.primary,
        selectedContentColor = Color.White
    )
)

Tiny 变体

kotlin
val tabs = listOf("照片", "视频", "人像")
var selectedTabIndex by remember { mutableStateOf(0) }

TabRowWithContour(
    tabs = tabs,
    selectedTabIndex = selectedTabIndex,
    onTabSelected = { selectedTabIndex = it },
    height = TabRowDefaults.TabRowWithContourTinyHeight,
    cornerRadius = TabRowDefaults.TabRowWithContourTinyCornerRadius,
    contourPadding = TabRowDefaults.TabRowWithContourTinyPadding
)

与 Pager 结合使用

kotlin
val tabs = listOf("页面1", "页面2", "页面3")
val pagerState = rememberPagerState { tabs.size }
var selectedTabIndex by remember { mutableStateOf(0) }

LaunchedEffect(pagerState.currentPage) {
    selectedTabIndex = pagerState.currentPage
}

LaunchedEffect(selectedTabIndex) {
    pagerState.animateScrollToPage(selectedTabIndex)
}

Surface {
    Column {
        TabRow(
            tabs = tabs,
            selectedTabIndex = selectedTabIndex,
            onTabSelected = { selectedTabIndex = it }
        )
        HorizontalPager(
            pagerState = pagerState,
            modifier = Modifier.fillMaxSize()
        ) { page ->
            Box(
                modifier = Modifier.fillMaxSize(),
                contentAlignment = Alignment.Center
            ) {
                Text("页面内容 ${page + 1}")
            }
        }
    }
}

变更日志

基于 Apache-2.0 许可发布