前言

很多人第一次用 Divider(),做出来的页面都一个味儿:线是有了,但信息层级没出来,列表还是像一整块糊在一起。这个问题在设置页、个人中心、资料面板里尤其明显。

这一篇我想讲的不是“怎么画一条线”,而是怎么把 Divider 真正用到列表结构里。案例里其实给了三个很典型的方向:普通列表项分隔、分组列表分隔,以及 List 组件的内置分割线思路。你把这三种方式吃透,后面做设置页基本就稳了。

为一篇 HarmonyOS7 技术教程绘制一张手绘笔记风信息图,主题是“列表分隔线不是画线,而是组织

这个案例到底在解决什么

案例本身围绕一个设置页结构展开,页面里有几类常见场景:

  • 普通一维列表,条目之间需要轻分隔
  • 分组列表,不同模块之间既要分开,又要保持同组的连续感
  • 文本说明区,用来补充 List().divider() 这种内置能力

它的重点不是炫技,而是让用户一眼看懂“这几项属于一组”“哪些内容是并列的”“哪里是模块边界”。

先看完整代码

import { DEMO_BG_COLOR, DEMO_CARD_COLOR, DEMO_THEME_COLOR, DEMO_SUBTEXT_COLOR } from './types'

@Entry
@Component
struct SettingsListDividerPatterns {
  @State isShow: boolean = true

  build() {
    Column() {
      if (this.isShow) {
        Scroll() {
          Column({ space: 16 }) {
            Text('列表分隔策略').fontSize(16).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)

            Column() {
              Text('列表项分隔').fontSize(13).fontColor('#4D96FF').margin({ bottom: 8 })
              ForEach(['个人信息', '账号安全', '通知设置', '隐私设置', '关于我们'], (item: string, idx: number) => {
                Column() {
                  Row() {
                    Text(item).fontSize(14).fontColor('#1A1A1A')
                    Blank()
                    Text('>').fontSize(14).fontColor('#CCCCCC')
                  }.width('100%').padding({ left: 4, right: 4 })

                  if (idx < 4) {
                    Divider().strokeWidth(0.5).color('#E8E8E8').margin({ top: 10, bottom: 10 })
                  }
                }
              })
            }
            .backgroundColor(DEMO_CARD_COLOR)
            .padding(14)
            .borderRadius(12)

            Column() {
              Text('分组列表分隔').fontSize(13).fontColor('#6BCB77').margin({ bottom: 8 })

              Column() {
                Text('基础设置')
                  .fontSize(12)
                  .fontColor(DEMO_THEME_COLOR)
                  .fontWeight(FontWeight.Bold)
                  .padding({ left: 10, top: 8, bottom: 4 })

                Column({ space: 0 }) {
                  Row() {
                    Text('修改密码').fontSize(13).padding(10)
                    Blank()
                    Text('>').fontSize(13).fontColor('#CCCCCC')
                  }
                  Divider().strokeWidth(0.5).color('#F0F0F0').margin({ left: 10 })
                  Row() {
                    Text('绑定手机').fontSize(13).padding(10)
                    Blank()
                    Text('已绑定').fontSize(12).fontColor('#6BCB77')
                  }
                }
              }
              .backgroundColor(DEMO_CARD_COLOR)
              .borderRadius(8)

              Column() {
                Text('高级设置')
                  .fontSize(12)
                  .fontColor('#FFA500')
                  .fontWeight(FontWeight.Bold)
                  .padding({ left: 10, top: 8, bottom: 4 })

                Column({ space: 0 }) {
                  Row() {
                    Text('深色模式').fontSize(13).padding(10)
                    Blank()
                    Text('>').fontSize(13).fontColor('#CCCCCC')
                  }
                  Divider().strokeWidth(0.5).color('#F0F0F0').margin({ left: 10 })
                  Row() {
                    Text('语言设置').fontSize(13).padding(10)
                    Blank()
                    Text('简体中文').fontSize(12).fontColor(DEMO_SUBTEXT_COLOR)
                  }
                  Divider().strokeWidth(0.5).color('#F0F0F0').margin({ left: 10 })
                  Row() {
                    Text('清除缓存').fontSize(13).padding(10)
                    Blank()
                    Text('128 MB').fontSize(12).fontColor(DEMO_SUBTEXT_COLOR)
                  }
                }
              }
              .backgroundColor(DEMO_CARD_COLOR)
              .borderRadius(8)
            }
            .backgroundColor('#F0FAF1')
            .padding(12)
            .borderRadius(12)

            Column({ space: 6 }) {
              Text('List 组件内置分割线').fontSize(13).fontColor('#9B59B6')
              Text('List().divider({ strokeWidth: 1, color: "#E0E0E0" })')
                .fontSize(12)
                .fontColor('#333333')
              Text('内置 divider 自动在列表项之间添加分割线')
                .fontSize(11)
                .fontColor(DEMO_SUBTEXT_COLOR)
            }
            .width('100%')
            .backgroundColor('#F5EEF8')
            .padding(12)
            .borderRadius(8)
          }
          .width('100%')
        }
      }

      Text('SettingsListDividerPatterns - 分组列表分隔线')
        .fontSize(12)
        .fontColor(DEMO_SUBTEXT_COLOR)
        .margin({ top: 12 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor(DEMO_BG_COLOR)
    .padding(16)
  }
}

为一篇 HarmonyOS7 ArkUI 教程绘制一张手绘笔记风框架图,主题是“SettingsLi

为一篇 HarmonyOS7 技术教程绘制一张手绘笔记风对比图,主题是“同样是分隔线,写法不同,列表

第一层:普通列表怎么加线

最基础的做法,是在每个条目下面放一条分割线,但最后一项不要加。这一点看着小,实际很重要。因为最后一项如果还带一条线,视觉上会像“列表没结束”。

关键代码是这一段:

ForEach(['个人信息', '账号安全', '通知设置', '隐私设置', '关于我们'], (item: string, idx: number) => {
  Column() {
    Row() {
      Text(item)
      Blank()
      Text('>')
    }

    if (idx < 4) {
      Divider().strokeWidth(0.5).color('#E8E8E8').margin({ top: 10, bottom: 10 })
    }
  }
})

这里有三个点要单独说。

ForEach 给了你索引 idx,所以你可以很轻松地判断“是不是最后一项”。这种写法比统一渲染后再额外处理边界更直观。

strokeWidth(0.5) 用的是细线。设置页这种偏中性的界面,分隔线应该弱一点,它是配角,不应该抢正文的存在感。

margin({ top: 10, bottom: 10 }) 也很关键。线和文字贴太近,会显得界面很挤。分隔线真正分开的不是像素,而是阅读节奏。

第二层:分组列表怎么做出层次

案例里更有价值的部分,其实是分组结构。

它不是简单地“上下两块内容”,而是先给每组一个标题,再在组内继续使用轻量分隔。这样用户看到页面时,会先识别模块,再识别条目。

例如“基础设置”和“高级设置”这两块:

Text('基础设置')
  .fontSize(12)
  .fontColor(DEMO_THEME_COLOR)
  .fontWeight(FontWeight.Bold)
  .padding({ left: 10, top: 8, bottom: 4 })

这里标题字号更小,但用了加粗和主题色。意思很明确:它不是主要操作项,而是导航性的分组标题。

组内分割线又用了另一种处理:

Divider().strokeWidth(0.5).color('#F0F0F0').margin({ left: 10 })

这条线不是全宽,而是左侧缩进。缩进的作用,是让线条和右侧信息区对齐,保留左边标题文字的呼吸感。你在做资料页、订单页、表单确认页时,这种缩进线非常常见。

Blank() 在这个案例里为什么也重要

虽然主题是 Divider,但 Blank() 才是整行结构稳定的关键。

每一个 Row() 里都用它把左侧主信息和右侧说明、箭头推开:

Row() {
  Text('语言设置').fontSize(13).padding(10)
  Blank()
  Text('简体中文').fontSize(12).fontColor(DEMO_SUBTEXT_COLOR)
}

如果没有 Blank(),右边状态文字很容易受前面内容长度影响,界面就会开始歪。很多人觉得自己是在调分割线,其实真正乱的是行内布局。

第三个思路:什么时候该用 List().divider()

案例最后专门提到一个知识点:List 组件自带 divider 配置。

List().divider({ strokeWidth: 1, color: '#E0E0E0' })

这个能力适合什么场景?答案是:当你的内容本来就是标准列表,而且每项结构一致时。

它的优势是省事,条目之间的分割规则统一,维护成本低。尤其在消息列表、联系人列表、菜单列表里,直接用内置分割线会更省心。

但如果你要做的是分组设置页、带缩进规则的复杂信息区,手动用 Divider() 会更灵活。因为你需要控制哪条线全宽、哪条线缩进、哪组之间留多少空白,这些内置分割线不一定够用。

这类页面最容易踩的几个坑

第一个坑,是线太重。颜色太深、宽度太粗,页面会显得廉价又杂乱。

第二个坑,是所有线都全宽。这样虽然整齐,但层级感会消失,分组边界和组内边界看起来没有区别。

第三个坑,是最后一项也保留分割线。这个细节很小,但用户会下意识感觉页面“没收住”。

第四个坑,是只画线,不调整行高和间距。分隔线不能单独存在,它必须和 padding、字号、颜色一起工作。

可以怎么改造成真实业务页面

这个案例稍微改一下,就能直接变成真实设置页。

你可以把“基础设置”换成账号类,把“高级设置”换成通用偏好;右侧文字可以替换成当前值,比如“手机号”“语言”“缓存大小”;点击行再配上路由跳转,页面就能用了。

如果你做的是商城、社交、工具类 App,这种分组列表结构几乎一定会出现。真正好用的关键,不在于有多少视觉效果,而在于用户扫一眼就知道应该点哪里。

写在最后

Divider() 不是一个存在感很强的组件,但它决定了页面是不是有秩序。很多时候,用户不会注意到你加了一条线,但一定会感觉到这个页面“看着舒服”还是“看着乱”。

这个案例最值得拿走的,不是某一条 API,而是三个分隔思路:普通列表轻分隔、分组列表缩进分隔、标准列表用内置分隔。后面你再做资料页、设置页、订单明细页,会顺手很多。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐