Skip to content

ListItem — 通用列表项 ​

单张卡片式的列表行:左边一个图标容器,中间标题 + 副标题,右边最多两个图标操作或一个自定义插槽。

基本用法 ​

最简形式:

kotlin
ListItem(
    title = "清理缓存",
    subtitle = "当前占用 128 MB",
    icon = Phosphor.Broom,
    onClick = { /* … */ },
)

右侧放操作按钮:

kotlin
ListItem(
    title = "下载目录",
    subtitle = "/storage/emulated/0/Download",
    icon = Phosphor.Folder,
    actionIcon1 = Phosphor.PencilSimple,
    onAction1Click = { /* 重命名 */ },
    actionIcon2 = Phosphor.Trash,
    onAction2Click = { /* 删除 */ },
)

右侧放任意内容(开关、箭头、计数):

kotlin
ListItem(
    title = "自动保存",
    icon = Phosphor.Gear,
    trailing = {
        Switch(checked = autoSave, onCheckedChange = { autoSave = it })
    },
)

用图片当左侧图标:

kotlin
ListItem(
    title = "示例图片",
    iconUrl = "https://example.com/cover.jpg",
    onClick = { /* … */ },
)

参数 ​

参数类型默认值说明
titleString—标题,单行、超长省略
modifierModifierModifier修饰符
subtitleString?null副标题,最多两行、超长省略。空白字符串等同于不传
iconImageVector?null左侧图标(与 iconUrl 二选一)
iconUrlString?null左侧图片 URL,Coil 加载、ContentScale.Crop
iconBackgroundColorColorprimaryContainer图标容器底色
iconTintColoronPrimaryContainer图标颜色
actionIcon1ImageVector?null右侧第一个图标按钮
actionIcon1TintColoronSurfaceVariant第一个图标颜色
onAction1Click(() -> Unit)?null第一个图标点击
actionIcon2ImageVector?null右侧第二个图标按钮
actionIcon2TintColoronSurfaceVariant第二个图标颜色
onAction2Click(() -> Unit)?null第二个图标点击
trailing@Composable (() -> Unit)?null自定义右侧插槽,优先级高于 actionIcon1 / actionIcon2
onClick(() -> Unit)?null整行点击。传 null 时整行不可点

要点 ​

  • icon 和 iconUrl 只给一个。 两个都传时只有 icon 生效(iconUrl 那个分支进不去)。两个都不给,左侧整块不渲染,标题会顶到 20dp 内边距上。
  • trailing 一旦传了,actionIcon1 / actionIcon2 全部失效 —— 代码是 if (trailing != null) … else …。想在自定义插槽旁边再放一个图标按钮,自己在 trailing 里排。
  • 图标按钮必须 icon 和 click 同时给。 判断条件是 actionIcon1 != null && onAction1Click != null,只给图标不会渲染出来。这是防呆:避免画出一个「点了没反应」的按钮。
  • onClick = null 时整行不可点 —— 内部走 Surface(enabled = onClick != null),所以不只是「点了没反应」,连水波纹和按压态都没有。纯展示的行就不用传。
  • 别用 modifier 覆盖尺寸。 图标容器 48dp、右侧按钮 40dp 都是标定过的值。
  • subtitle 传空串和传 null 效果一样(内部用 isNullOrBlank() 判)。

说明 ​

  • 图标容器 48dp:原来的 42dp 是「差一点到触控标准」的尴尬尺寸;48dp 同时满足视觉重量和 M3 的最小触控尺寸。
  • 内边距 20 / 16:比常见的 16 / 12 更从容,一屏之内不拥挤优先于「一屏多塞一行」。
  • 标题用 titleMedium、副标题用 bodySmall:标题该比正文更重。两者都带省略号,超长不会撑破布局。
  • 标题与副标题之间是 3dp,紧凑但不粘。
  • trailing 插槽前自带 12dp 间距,自己不用再补。
  • 形状是 AppShapes.row、底色透明:单行本身不画背景,放进什么容器就融进什么容器。想要卡片质感,自己在外层给 background + clip。