前言

很多初学者第一次做页面时,最容易犯的一个错,就是把尺寸写死。

宽度写成固定值,首屏看着没问题,换个设备就开始挤;横竖屏一切,比例又乱;到了平板或更宽的窗口里,本来应该拉开的内容还是挤在一小块地方。

这篇案例虽然名字里带的是 Image,但它真正想讲的其实是更基础的一件事:当容器大小变化时,内容区域该怎么分配宽度。

如果你后面要做图片卡片区、响应式相册、媒体列表或者多端适配页,这篇会很有用。

一张适合技术教程文章的手绘笔记风信息图,主题是“HarmonyOS7 ResponsiveImage

这个案例在演示什么

这份代码主要演示了三种常见的宽度分配方式:

  1. 百分比宽度
  2. layoutWeight 弹性分配
  3. 常见响应式场景说明

这三种思路看起来都在“调宽度”,但其实适用场景不一样。

方式 更适合什么场景

一张手绘笔记风对比图,比较 HarmonyOS7 中三种宽度分配方式的差异。画面分三列并排:左列是百

| width('25%') 这种百分比 | 已知比例的固定分栏 |
| layoutWeight(1) | 需要根据剩余空间弹性分配 |
| 约束 + 断点思路 | 多设备、多列布局 |

完整代码

/**
 * ResponsiveImageLayout - Image 响应式布局
 * 演示 Image 如何适应容器大小变化
 */
import { PRESET_COLORS, generateListItems, PAGE_BG_COLOR, PANEL_BG_COLOR, ACCENT_COLOR, MUTED_TEXT_COLOR } from './types'

@Entry
@Component
struct ResponsiveImageLayout {
  @State isShow: boolean = true
  @State containerWidth: number = 100
  @State containerHeight: number = 120

  build() {
    Column() {
      if (this.isShow) {
        Scroll() {
          Column({ space: 16 }) {
            Text('Image 响应式布局').fontSize(16).fontColor(ACCENT_COLOR).fontWeight(FontWeight.Bold)

            Column() {
              Text('百分比宽度适应').fontSize(13).fontColor('#4D96FF').margin({ bottom: 8 })
              Row({ space: 4 }) {
                Column() { Text('25%').fontSize(10).fontColor('#FFF') }
                  .width('25%').height(60).backgroundColor('#4D96FF').borderRadius(4).justifyContent(FlexAlign.Center)
                Column() { Text('50%').fontSize(11).fontColor('#FFF') }
                  .width('50%').height(60).backgroundColor('#FFA500').borderRadius(4).justifyContent(FlexAlign.Center)
                Column() { Text('25%').fontSize(10).fontColor('#FFF') }
                  .width('25%').height(60).backgroundColor('#6BCB77').borderRadius(4).justifyContent(FlexAlign.Center)
              }.width('100%')
            }
            .backgroundColor(PANEL_BG_COLOR).padding(12).borderRadius(12)

            Column() {
              Text('layoutWeight 等比分配').fontSize(13).fontColor('#6BCB77').margin({ bottom: 8 })
              Row({ space: 6 }) {
                Column() { Text('1').fontSize(12).fontColor('#FFF') }
                  .layoutWeight(1).height(70).backgroundColor('#FF6B6B').borderRadius(6).justifyContent(FlexAlign.Center)
                Column() { Text('2').fontSize(12).fontColor('#FFF') }
                  .layoutWeight(2).height(70).backgroundColor('#FFD93D').borderRadius(6).justifyContent(FlexAlign.Center)
                Column() { Text('1').fontSize(12).fontColor('#FFF') }
                  .layoutWeight(1).height(70).backgroundColor('#9B59B6').borderRadius(6).justifyContent(FlexAlign.Center)
              }.width('100%')
            }
            .backgroundColor('#F0FAF1').padding(12).borderRadius(12)

            Column() {
              Text('常见响应式场景').fontSize(13).fontColor('#FFA500').margin({ bottom: 8 })
              Column({ space: 5 }) {
                Text('手机全宽: width("100%")').fontSize(12).fontColor('#666666')
                Text('平板2列: width("50%")').fontSize(12).fontColor('#666666')
                Text('PC 3列: width("33.3%")').fontSize(12).fontColor('#666666')
                Text('弹性: .layoutWeight(1) 动态分配').fontSize(12).fontColor('#666666')
                Text('约束: .constraintSize({ minWidth, maxWidth })').fontSize(12).fontColor('#666666')
              }
            }
            .width('100%').backgroundColor('#FFF8E8').padding(12).borderRadius(8)
          }.width('100%')
        }
      }
      Text('Image 响应式 - 宽度百分比 / layoutWeight / 约束')
        .fontSize(12).fontColor(MUTED_TEXT_COLOR).margin({ top: 12 })
    }
    .width('100%').height('100%').backgroundColor(PAGE_BG_COLOR).padding(16)
  }
}

一张手绘流程图,说明做响应式图片区域时的判断路径。流程从“容器尺寸变化”开始,依次分支到“是否已知固

百分比宽度为什么适合“已知比例”的区域

先看第一块:

.width('25%')
.width('50%')
.width('25%')

这类写法非常直接,意思也很明确:整行分成 25% + 50% + 25%

它最适合那些比例关系你一开始就已经想清楚的布局。

比如:

  • 中间主图更大,两边缩略区更小
  • 主内容区和边侧辅助区有固定比例
  • 左右信息区需要不对称分栏

它的优点是稳定、直观;缺点是灵活性没那么强。

layoutWeight 为什么更像“把剩余空间交给系统分”

再看第二块:

.layoutWeight(1)
.layoutWeight(2)
.layoutWeight(1)

这组值可以理解成 1 : 2 : 1 的分配关系。

它和百分比宽度的差别在于:这里不是直接写死每一块占多少,而是告诉布局系统“剩余空间按这个权重来分”。

这种方式更适合:

  • 容器宽度经常变化
  • 元素之间需要柔性伸缩
  • 不想手算百分比

如果你后面做图片卡片栅格、推荐位、工具栏或者信息面板,这种写法会非常顺手。

为什么这篇虽然是 Image 主题,但重点其实是容器

你会发现,这个案例里并没有真正加载图片,而是用彩色块来模拟图片区域。

这并不是偷懒,反而说明它的教学重点更明确:先把容器分配逻辑讲清楚,再把图片塞进去。

这个顺序是对的。

因为大多数“图片适配问题”,最后其实都不是图片本身的问题,而是:

  • 容器太窄
  • 容器比例不合理
  • 布局方式选错了

constraintSize 为什么值得提前知道

案例最后提到了:

.constraintSize({ minWidth, maxWidth })

虽然这里没有展开写完整代码,但这个思路非常重要。

因为响应式布局真正稳定的做法,往往不是只靠百分比或者权重,而是还要给组件加上下限和上限。

比如:

  • 最小不能小于某个宽度,否则图片看不清
  • 最大不能无限拉伸,否则内容太空

这就是为什么很多成熟页面不是单靠一种布局方式,而是“比例 + 弹性 + 约束”一起用。

这篇最值得记住的 3 件事

1. 百分比宽度适合已知比例

当你明确知道区块应该占多少时,百分比最直白。

2. layoutWeight 适合剩余空间分配

它更适合做弹性布局,不需要你手算每一块的精确占比。

3. 图片适配问题,很多时候本质是容器分配问题

先把容器想清楚,再谈图片怎么显示,顺序别反了。

小白最容易踩的坑

1. 一上来就写固定宽高

这样在不同设备上很容易出问题。

2. 把百分比和弹性布局混着写,却没想清优先关系

结果往往是布局能跑,但很难维护。

3. 只看手机效果,不看宽屏和平板

响应式的意义就在于多尺寸下都能保持基本秩序。

这篇代码可以怎么改成真实业务

场景 改法
相册卡片区 用百分比做多列图片布局
推荐位模块 layoutWeight 做主卡片 + 次卡片排布
多端内容页 给图片区域补 constraintSize 做上下限控制
平板适配页 根据宽度切成 2 列或 3 列

动手改一改

  • 25% / 50% / 25% 改成 30% / 40% / 30%,观察效果。
  • layoutWeight(1,2,1) 改成 1,1,1,比较视觉差别。
  • 给某个区块补 constraintSize,限制它最小宽度。
  • 尝试把彩色块换成图片卡片结构。

写在最后

响应式布局这件事,说白了就是别让页面只在一种尺寸下好看。你写的不是“当前手机上的一张截图”,而是一个会在不同容器里活着的界面。

如果你现在还是 HarmonyOS7 初学者,我建议你把这篇里的三种思路都亲手改一遍。等你真的能把“固定比例、弹性权重、尺寸约束”分清楚,后面做图片页和卡片页会轻松很多。

更多推荐