一、线性布局(Row / Column)

方向 语法糖 适用
水平 Row 工具栏、按钮组
垂直 Column 表单、列表项
Column({ space: 8 }) {
  Text('用户名').fontSize(16)
  TextInput().placeholder('请输入')
  Button('登录')
}.width('100%').padding(16)

关键属性速记
justifyContent → 主轴对齐
alignItems → 交叉轴对齐
space → 相邻子组件间距


二、弹性布局(Flex)

一句话Flex = Row + Column + wrap + layoutWeight

Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
  ForEach([1,2,3,4,5], () => {
    Text('标签').layoutWeight(1).margin(4)
  })
}
场景 推荐值
等分 layoutWeight(1)
拉齐尾部 justifyContent: FlexAlign.SpaceBetween
换行 wrap: FlexWrap.Wrap

三、层叠布局(Stack)

Stack({ alignContent: Alignment.BottomEnd }) {
  Image($r('app.media.bg'))
  FloatingActionButton()   // 悬浮按钮
    .margin(16)
}

zIndex 越大越靠上;支持 hitTestBehavior 控制事件穿透。


四、相对布局(RelativeContainer)

通过 9 个锚点(上/下/左/右/居中)精准定位:

RelativeContainer() {
  Text('A').id('A')
    .alignRules({
      top: { anchor: '__container__', align: VerticalAlign.Top },
      left: { anchor: '__container__', align: HorizontalAlign.Start }
    })
  Text('B').id('B')
    .alignRules({
      left: { anchor: 'A', align: HorizontalAlign.End },
      centerVertical: { anchor: 'A' }
    })
}

五、栅格布局(GridRow / GridCol)

12 栅格系统,断点自动切换:

GridRow({ gutter: 12 }) {
  ForEach(this.newsList, item =>
    GridCol({ span: { sm: 12, md: 6, lg: 4 } }) {
      NewsCard({ item })
    }
  )
}
断点 典型宽度 列数
sm <520 vp 12
md 520-840 12
lg >840 12

span 取值 1-12,必须 父容器设置 columns: 12(默认即 12)。


六、网格布局(Grid)

适用于 固定行列 的棋盘、相册、九宫格:

Grid() {
  ForEach(this.imgList, img =>
    GridItem() {
      Image(img).objectFit(ImageFit.Cover)
    }
  )
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr')
.columnsGap(8)
.rowsGap(8)

七、瀑布流布局(WaterFlow)

子项高度可变,自动填满空白;

WaterFlow() {
  LazyForEach(this.dataSource, item =>
    FlowItem() {
      ProductCard({ item })
    }
  )
}
.columnsGap(12)
.rowsGap(12)
.columnsTemplate('1fr 1fr')   // 两列

八、列表布局(List)

长列表首选,支持懒加载 + 滑动事件:

List({ lanes: { sm: 1, md: 2, lg: 3 } }) {
  LazyForEach(this.dataSource, item =>
    ListItem() {
      ArticleRow({ item })
    }
  )
}
.onScrollIndex(start => console.log('开始索引:' + start))

九、轮播布局(Swiper)

Swiper() {
  ForEach(this.banners, banner =>
    Image(banner.url).borderRadius(12)
  )
}
.autoPlay(true)
.interval(3000)
.indicator(true)
.displayCount({ sm: 1, md: 2, lg: 3 })   // 响应式

十、页签布局(Tabs)

底部、顶部、侧边一键切换

Tabs({ barPosition: BarPosition.End }) {
  TabContent() { HomePage() }.tabBar('首页')
  TabContent() { ProfilePage() }.tabBar('我的')
}
.vertical(false)          // true=侧边
.scrollable(true)         // 支持手势滑动

十一、抽屉布局(SideBarContainer)

官方抽屉,零代码手势

SideBarContainer(SideBarContainerType.Embed) {
  Column() { /* 抽屉内容 */ }.width(240)
}
.controlButton({
  top: 24,
  left: 24,
  icons: {
    shown: $r('app.media.menu'),
    hidden: $r('app.media.close')
  }
})

十二、导航布局(Navigation)

单/双/三分栏一站式导航,自动适配折叠屏

Navigation() {
  NavRouter() {
    Text('一级')
    NavDestination() { DetailPage() }
  }
}
.mode(NavigationMode.Auto)   // Auto=根据宽度自动分栏

十三、原子布局(DisplayPriority & PriorityLayout)

空间不足时按优先级隐藏:

Row() {
  Text('必须').displayPriority(2)
  Text('可隐藏').displayPriority(1)
}

优先级 越大被隐藏;默认 0 表示不隐藏。


十四、响应式布局 2×2 简化断点

状态 阈值 目录名
横向 Compact <600 vp hC
横向 Regular ≥600 vp hR
纵向 Compact <800 vp vC
纵向 Regular ≥800 vp vR

十五、常见错误 10 秒定位表

现象 根因 1 行解决
栅格 span 无效 父容器未 columns:12 GridRow({columns:12})
layoutWeight 无效 父容器无主轴尺寸 Row/Column 显式 width/height
图片溢出 objectFit .objectFit(ImageFit.Cover)
断点监听无回调 responsiveWindow module.json5 里开启
通知不显示 缺权限 动态申请 ohos.permission.NOTIFICATION
Logo

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

更多推荐