外观
PillLabel / PillLabelsRow / PillLabelsColumn — 标签
普通胶囊标签,以及横 / 纵两个方向的标签容器。
PillLabel 和 PillTab 长得几乎一样,区别是没有选中态:每个标签平等,不存在「当前选中」这个概念(筛选条件里的普通 tag、可点击的入口标签、「支持平台」这类说明标签)。
基本用法
单个标签:
kotlin
PillLabel(label = "已完结") // 纯展示,不可点
PillLabel(label = "科幻", onClick = { filter("科幻") })
PillLabel(label = "全部", icon = Phosphor.Star, count = 128)
PillLabel(label = "同步中", icon = Phosphor.ArrowsClockwise, onClick = { })横向标签行(自带横滚):
kotlin
PillLabelsRow(
labels = listOf("全部", "科幻", "悬疑", "日常"),
onClick = { index -> selected = index },
leading = { ActionImageButton(Phosphor.Funnel, onAction = { openFilter() }) },
)纵向标签列:
kotlin
PillLabelsColumn(
labels = listOf("最近阅读", "我的收藏", "下载管理"),
onClick = { index -> nav(index) },
itemAlignment = Alignment.CenterHorizontally,
)参数
PillLabel
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
label | String | — | 标签文字,单行、不换行 |
onClick | (() -> Unit)? | null | 传 null = 纯展示、不可点击 |
modifier | Modifier | Modifier | 修饰符 |
size | LabelSize | LabelSize.MEDIUM | 尺寸档位 |
enabled | Boolean | true | 只在可点击时生效 |
icon | ImageVector? | null | 左侧图标 |
count | Int? | null | 右侧数字角标 |
trailingContent | @Composable (() -> Unit)? | null | 右侧自定义插槽,优先级高于 count |
PillLabelsRow / PillLabelsColumn
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
labels | List<String> | — | 标签文字列表 |
onClick | ((Int) -> Unit)? | null | 点击回调,参数是下标;传 null = 整组纯展示 |
modifier | Modifier | Modifier | 修饰符 |
size | LabelSize | LabelSize.MEDIUM | 应用到组内每一个标签 |
leading | (@Composable () -> Unit)? | null | 行首 / 列首的自定义插槽,属于这一组内容、会跟着一起滚 |
itemAlignment | Alignment.Horizontal | Alignment.Start | 仅 PillLabelsColumn。列内每个标签的横向对齐 |
LabelSize
| 档位 | 高度 | 文字 | 图标 | 图标 / 角标间距 | 左右内边距 |
|---|---|---|---|---|---|
SMALL | 28dp | labelSmall | 14dp | 6dp | 12dp |
MEDIUM | 34dp | labelLarge | 16dp | 8dp | 16dp |
LARGE | 40dp | titleSmall | 18dp | 10dp | 20dp |
要点
onClick = null是真的不可点。 内部压根不加clickable—— 不只是「点了没反应」,连水波纹都没有。纯展示的标签就该这么用。enabled只在可点击时有意义。 不可点的标签传enabled = false不会变灰,因为那条分支根本走不到。- 禁用时只有文字和图标变灰(
onSurface@38%),描边不变 —— 边框恒为outlineVariant。观感上是「淡字 + 实边」,不是整体弱化。 trailingContent优先于count。 两个都传时只渲染trailingContent。leading是这一组内容的一部分,会跟着一起滚。 它不是盖在行上方的常驻控件 —— 那是标题栏的活。PillLabelsRow会撑满整宽(内部fillMaxWidth()),PillLabelsColumn不会。- 两个方向的标签间距都是 8dp,别在外层再加
Arrangement.spacedBy。 PillLabel的描边是outlineVariant,PillTab未选中是outline。 前者更淡:标签是「说明」级别,导航才是需要一眼看清的。别统一成一种。
说明
- 命名变更:
Label/LabelsRow/LabelsColumn已改名为PillLabel/PillLabelsRow/PillLabelsColumn,和PillTab一族对齐(形状前缀加在组件上)。这三个旧名字在组件库里都已不存在。 LabelSize保留原名 —— 尺寸枚举不带形状前缀。- 三档规格收在一份配置表里(高度 + 文字 + 图标 + 间距 + 内边距),所以改尺寸只改一处。这也是三档之间「视觉重量一致」的实现方式:图标和内边距跟着高度同比例走,而不是各自硬编码。
PillLabelsRow/PillLabelsColumn是同一件事的两个方向:需要竖排(侧栏式标签、长标签不适合横滚)时用列。两者的leading、size、回调下标语义完全对称。- 和
PillTab的分工:需要「当前选中哪一个」用PillTab/PillTabsRow;只是展示、或者平级多选(筛选条件)用PillLabel/PillLabelsRow。