为文章《HarmonyOS7 BlankFlexibleSpacing 教程:用 Blank() 把

前言

如果说 Blank() 的基础用法是在一行里把左右两端撑开,那么它更有意思的地方,其实是在稍微复杂一点的业务行布局里。

真实页面里,一行内容往往不止两个元素。左边可能是标签,中间是说明,右边是数值或状态,再加上分隔线和层级组织。如果这些内容全靠 margin 去硬凑,后面会越来越难维护。

这份案例就很适合继续往前走一步,看看 Blank() 在更真实的业务行场景里是怎么工作的。

这份案例在演示什么

页面主要展示了三种使用思路:

  1. 单个 Blank() 占据剩余空间
  2. 多个 Blank() 平均分配空白
  3. 在实际数据行中组织标签、说明和数值

为文章中的“这份案例在演示什么”部分绘制一张手绘流程图,主题是“Blank 弹性布局的三种工作方式”

它比上一类基础示例更接近产品页面。

完整代码

/**
 * BlankFlexibleSpacing - Blank 弹性分配
 * 演示 Blank 组件的 min/max 约束限制
 */
import { PRESET_COLORS, generateListItems, PAGE_BG_COLOR, PANEL_BG_COLOR, ACCENT_COLOR, MUTED_TEXT_COLOR } from './types'

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

  build() {
    Column() {
      if (this.isShow) {
        Scroll() {
          Column({ space: 16 }) {
            Text('Blank 弹性约束').fontSize(16).fontColor(ACCENT_COLOR).fontWeight(FontWeight.Bold)

            Column() {
              Text('Blank 最小宽度约束').fontSize(13).fontColor('#4D96FF').margin({ bottom: 8 })
              Row() {
                Text('左').padding(8).backgroundColor('#4D96FF').fontColor('#FFFFFF').borderRadius(4).fontSize(12)
                Blank().backgroundColor('#E8F4FD').width('100%')
                Text('右').padding(8).backgroundColor('#FFA500').fontColor('#FFFFFF').borderRadius(4).fontSize(12)
              }.width('100%').height(40)
              Text('Blank 自动占据剩余空间').fontSize(11).fontColor(MUTED_TEXT_COLOR).margin({ top: 4 })
            }
            .backgroundColor(PANEL_BG_COLOR).padding(12).borderRadius(12)

            Column() {
              Text('多个 Blank 等分剩余空间').fontSize(13).fontColor('#6BCB77').margin({ bottom: 8 })
              Row() {
                Text('1').padding(8).backgroundColor('#6BCB77').fontColor('#FFFFFF').borderRadius(4).fontSize(12)
                Blank()
                Text('2').padding(8).backgroundColor('#4ECDC4').fontColor('#FFFFFF').borderRadius(4).fontSize(12)
                Blank()
                Text('3').padding(8).backgroundColor('#FFD93D').fontColor('#FFFFFF').borderRadius(4).fontSize(12)
              }.width('100%').height(40)
            }
            .backgroundColor('#F0FAF1').padding(12).borderRadius(12)

            Column() {
              Text('实际应用场景').fontSize(13).fontColor('#9B59B6').margin({ bottom: 10 })
              Column({ space: 10 }) {
                Row() {
                  Text('技能').padding({ left: 8, right: 8, top: 4, bottom: 4 }).fontSize(11).fontColor('#FFFFFF').backgroundColor(ACCENT_COLOR).borderRadius(4)
                  Blank()
                  Text('等级').fontSize(12).fontColor(MUTED_TEXT_COLOR)
                  Text('85').fontSize(14).fontColor('#FFA500').fontWeight(FontWeight.Bold).margin({ left: 8 })
                }.width('100%')
                Divider().strokeWidth(0.5).color('#E0E0E0')
                Row() {
                  Text('经验').padding({ left: 8, right: 8, top: 4, bottom: 4 }).fontSize(11).fontColor('#FFFFFF').backgroundColor('#6BCB77').borderRadius(4)
                  Blank()
                  Text('进度').fontSize(12).fontColor(MUTED_TEXT_COLOR)
                  Text('60%').fontSize(14).fontColor('#6BCB77').fontWeight(FontWeight.Bold).margin({ left: 8 })
                }.width('100%')
                Divider().strokeWidth(0.5).color('#E0E0E0')
                Row() {
                  Text('金币').padding({ left: 8, right: 8, top: 4, bottom: 4 }).fontSize(11).fontColor('#FFFFFF').backgroundColor('#FFD93D').borderRadius(4)
                  Blank()
                  Text('数量').fontSize(12).fontColor(MUTED_TEXT_COLOR)
                  Text('1280').fontSize(14).fontColor('#FFD93D').fontWeight(FontWeight.Bold).margin({ left: 8 })
                }.width('100%')
              }
            }
            .backgroundColor('#F5EEF8').padding(14).borderRadius(12)
          }.width('100%')
        }
      }
      Text('Blank 弹性分配 - 让多元素行布局保持秩序')
        .fontSize(12).fontColor(MUTED_TEXT_COLOR).margin({ top: 12 })
    }
    .width('100%').height('100%').backgroundColor(PAGE_BG_COLOR).padding(16)
  }
}

为文章中“实际应用场景”的代码与说明绘制一张手绘框架图,主题是“复杂业务行里的 Blank 布局结构

为什么这篇更像“业务行布局训练”

第一篇 Blank 更偏基础认知,这篇则更接近真实页面里的信息行组织。

尤其是最后一块:

  • 左边是标签
  • 中间由 Blank() 吃掉剩余空间
  • 右边是说明项和数值

这就是非常典型的后台、工具类页面或资料展示页结构。

单个 Blank() 为什么适合承接“剩余空间”

先看第一块:

Text('左')
Blank().backgroundColor('#E8F4FD').width('100%')
Text('右')

这里的重点不是背景色,而是你能直观看到 Blank() 把中间剩余区域撑开了。

这种写法适合那些两端内容宽度不固定,但又必须被自然拉开的场景。

多个 Blank() 为什么还是很有价值

第二块延续了一个很重要的思路:

Text('1')
Blank()
Text('2')
Blank()
Text('3')

这表示不止一个空白区可以参与分配。对多元素横向布局来说,这非常实用。

比如:

  • 三段式信息排布
  • 多个简短筛选项
  • 分段工具条

真正值得看的,是最后的“实际应用场景”

这一组是整篇最有实战感的部分。以第一行举例:

Text('技能')
Blank()
Text('等级')
Text('85')

这个结构表达得很清楚:

  • 左侧是主标签
  • 右侧是一组关联信息
  • 中间空间自动拉开

这种模式在很多页面里都会反复出现,比如:

  • 个人资料概览
  • 设置项状态行
  • 数据看板指标行
  • 列表条目摘要区

为什么这里搭配 Divider() 很自然

案例在每行之间加了:

Divider().strokeWidth(0.5).color('#E0E0E0')

这说明 Blank() 很适合和 Divider() 一起使用。

原因很简单:

  • Blank() 负责整理一行内部秩序
  • Divider() 负责分开多行层级

一个管横向,一个管纵向,这两个组件经常会一起出现。

关键代码单独讲解

Blank().backgroundColor('#E8F4FD').width('100%')

这里给 Blank() 加背景色,是为了把它的占位区域直观展示出来,教学意义很强。

.margin({ left: 8 })

右侧数值和说明文字之间仍然保留了局部固定间距。它提醒你:Blank() 不是替代一切间距,而是解决结构性空白。

Column({ space: 10 })

多行数据区用统一的纵向节奏组织,再配上分割线,页面秩序会明显更稳定。

小白最容易踩的坑

1. 用 Blank() 解决所有细节间距

结果布局虽然能拉开,但局部文字关系反而不够精致。

2. 没想清主信息和次信息谁在左、谁在右

这样就算拉开了,也不一定好读。

3. 一行信息太多,导致 Blank() 再怎么分也显得拥挤

布局工具不是万能的,信息量本身也要克制。

这份代码能怎么改成真实业务

场景 改法
个人资料页 左侧字段名,右侧等级或状态值
后台面板 左侧指标,右侧趋势和当前数值
设置列表 左标签右说明,中间自动拉开
游戏角色页 左属性名,右属性值与评级

动手改一改

  • 把“技能 / 等级 / 85”这行改成你自己的业务数据结构。
  • 给某一行增加一个图标,再观察 Blank() 是否还保持稳定分配。
  • 尝试把三行数据做成可复用的子组件。
  • 把右侧说明和数值做成竖排结构,再比较阅读体验。

写在最后

真正有用的布局技巧,通常都不复杂。Blank() 就是这种组件。它没有很强的存在感,但特别适合把复杂行布局里的剩余空间处理得很自然。

如果你现在还在靠一堆 margin 硬凑业务行排版,这篇很值得拿来改一遍。等你开始能把“主信息、次信息、剩余空间”三者分清,很多列表和面板布局都会轻松下来。

Logo

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

更多推荐