HarmonyOS鸿蒙开发 | ArkUI组件与布局

HarmonyOS鸿蒙开发 | ArkUI组件与布局

在学习HarmonyOS ArkUI(方舟开发框架)时,整理了一份笔记,方便日后回顾。

本文档为HarmonyOS ArkUI(方舟开发框架)零基础入门学习笔记,基于ArkTS声明式开发范式编写,既适合新手快速上手鸿蒙界面开发,也可作为日常开发的速查手册。 开发环境为HarmonyOS官方开发工具 DevEco Studio


一、开发起步

核心开发工具

HarmonyOS界面开发的官方IDE为 DevEco Studio,内置代码编辑器、实时预览器、模拟器等全套开发工具,无需额外配置环境即可快速开发。

  • 代码编写:在 build() 函数内编写UI构建代码
  • 效果查看:通过右侧预览器查看界面效果
声明式UI核心结构

ArkTS声明式开发的核心是自定义组件 ,页面由一个或多个自定义组件组成。

所有UI结构必须在 build() 函数中声明。
build() 函数有且仅有一个根容器组件,不允许多个同级根元素。

  • 基础代码结构模板:
TypeScript 复制代码
@Entry   // 标记这是页面的入口组件  App启动时优先加载
@Component
struct Index {
  // 声明状态变量、常量等业务数据

  build() {
    // 唯一根容器组件
    Column() {
      // 界面内容:子组件、嵌套容器等
    }
    // 组件的属性样式  链式调用  建议每个属性独占一行
    .width('100%')
    .height('100%')
  }
}
装饰器 核心作用 使用规则
@Component 标记当前结构体为可复用的自定义组件 封装UI与逻辑 每个自定义组件必须添加该装饰器 结构体需实现build()函数
@Entry 标记当前组件为页面入口组件 一个页面仅需一个入口组件 预览器会优先渲染该组件

二、ArkUI核心思想:组件化布局

ArkUI(方舟开发框架)是鸿蒙官方主推的应用界面构建框架,核心采用组件化的声明式开发思想,所有界面元素都由组件构成,通过组件的组合、嵌套、样式配置完成界面开发。

组件分类
组件类型 核心作用 高频示例
基础组件 界面呈现的最小单元,负责内容展示与基础交互 文本Text、按钮Button、图片Image、输入框TextInput
容器组件 负责子组件的布局排列、尺寸约束,控制界面整体结构 列布局Column、行布局Row、列表List、堆叠布局Stack、弹性布局Flex
标准界面开发流程

遵循「 先排版 → 再填内容 → 最后美化 」的核心思路:

  1. 拆分界面结构,用容器组件完成整体行列排版,确定页面骨架。
  2. 在对应容器中放入基础组件,填充文本、图片、按钮等界面内容。
  3. 通过属性方法为组件设置样式、交互,完成界面美化与功能开发。

三、组件通用属性

通用属性可用于所有组件,用于约束组件尺寸、美化外观、控制位置,是界面开发的基础能力。

核心尺寸单位规范

鸿蒙开发中需严格区分3种核心单位(避免多设备适配异常):

单位 全称 适用场景 核心特性
vp Virtual Pixel 组件宽高、内边距、外边距、定位等布局尺寸 虚拟像素 会根据设备屏幕密度自动适配 保证不同设备视觉效果一致 是布局首选单位
fp Font Pixel 字体大小 跟随系统字体大小缩放 兼顾视觉效果与无障碍适配 是字体首选单位
px Pixel 仅特殊场景使用 设备物理像素点 不同设备分辨率差异大 不推荐直接用于布局 可通过vp2px()方法将vp转为px
基础通用属性
属性方法 作用说明 使用规则
.width(数值) 设置组件宽度 纯数值默认单位为vp 百分比需用单引号包裹 如 .width('100%').width(50)
.height(数值) 设置组件高度 纯数值默认单位为vp 百分比需用单引号包裹 只设置宽或高另一个维度会按原始比例自动缩放
.backgroundColor(颜色值) 设置组件背景色 支持颜色枚举 Color.颜色名 支持16进制色值'#十六进制色号' (16进制必须用单引号包裹)
.padding(数值/边距对象) 设置组件内边距 (内容与组件边缘的间距) 单数值为四边统一内边距 可单独指定边距:.padding({ left: 10, right: 10, top: 5, bottom: 5 })
.margin(数值/边距对象) 设置组件外边距 (组件与其他组件的间距) 单数值为四边统一外边距 可单独指定边距:.margin({ left: 10, right: 10, top: 5, bottom: 5 }) 两个相邻组件同时设置外边距则间距会叠加
边框 border
  • 作用:给组件添加边界,进行装饰美化。

  • 支持全方向统一配置和单方向单独配置

TypeScript 复制代码
// 四个方向统一边框
Text('统一边框')
  .border({
    width: 1,   // 边框宽度(必须设置)
    color: '#3274f6',   // 边框颜色(不设置则默认为黑色)
    style: BorderStyle.Solid   // 边框样式(不设置则默认为Solid实线)
  })

// 四个方向单独配置边框
Text('单独边框')
  .border({
    width: { top: 1, left: 2, right: 3, bottom: 1 },
    // width设置了哪些方向就有哪些方向的边框
    color: { left: Color.Blue, right: Color.Red },
    style: { left: BorderStyle.Dashed, right: BorderStyle.Dotted }
  })

// 边框样式:Solid实线、Dashed虚线、Dotted点线
圆角 borderRadius
  • 作用:设置组件边角弧度

  • 支持统一配置和单角单独配置

  • 可实现正圆、胶囊按钮等特殊效果

TypeScript 复制代码
// 四个圆角统一设置
Text('统一圆角')
  .borderRadius(5)

// 数值参数指圆的半径,通过不同的数值可以设置不同大小的圆角。
// 圆越大(数值大)则圆角越大  圆越小(数值小)则圆角越小

// 四个角单独设置
Text('单独圆角')
  .borderRadius({
    topLeft: 5,   // 左上角
    topRight: 5,   // 右上角
    bottomLeft: 10,   // 左下角
    bottomRight: 10   // 右下角
  })

// 特殊形状:正圆(宽高必须一致  圆角为宽高的一半)
Text('正圆')
  .width(100)
  .height(100)
  .borderRadius(50)   // 圆角是宽或高的一半
  .textAlign(TextAlign.Center)   // 文本居中显示

// 特殊形状:胶囊按钮(圆角为高度的一半)
Text('胶囊按钮')
  .width(150)
  .height(50)
  .borderRadius(25)   // 圆角是高的一半(横状胶囊按钮)
  .textAlign(TextAlign.Center)   // 文本居中显示
  // 竖状胶囊按钮:圆角是宽的一半

// 若同一个组件设置两个borderRadius属性 则新的圆角会覆盖旧的圆角

注意:同一组件重复设置borderRadius,后设置的会覆盖之前的配置。

背景图片相关属性
  • 用于给组件添加背景图片

  • 支持本地资源与网络资源

  • 可控制缩放、位置、平铺效果

属性方法 作用说明 参数
.backgroundImage(地址).backgroundImage(地址, 平铺方式) 设置背景图片源 不设置则默认不平铺 ImageRepeat.NoRepeat 水平平铺 ImageRepeat.X 垂直平铺 ImageRepeat.Y 水平垂直均平铺 ImageRepeat.XY
.backgroundImagePosition(参数) 调整背景图显示位置 支持坐标 { x: 坐标, y: 坐标 }(单位px 可用vp2px()转换为vp) 支持枚举 Alignment.Center(居中)等
.backgroundImageSize(参数) 控制背景图缩放 支持宽高对象: { width: 尺寸, height: 尺寸 } 宽高设置一边后另一边会自动等比例缩放 支持枚举: ImageSize.Auto 默认原图尺寸 ImageSize.Contain 完整显示、不变形、会留白) ImageSize.Cover 铺满容器、不变形、会裁切多余部分)
TypeScript 复制代码
Column()
  .width('100%')
  .height(300)
  .backgroundImage($r('app.media.bg'))
  .backgroundImageSize(ImageSize.Cover)
  .backgroundImagePosition(Alignment.Center)
绝对定位 position

作用:用于自由控制组件位置,可实现层叠效果。

核心特性:

  • 参照父组件左上角顶点进行偏移,无父组件则参照页面根容器。

  • 绝对定位后的组件不再占用原有布局位置,不影响其他组件的排列。

语法:.position(参数)

TypeScript 复制代码
Stack() {
  // 底层组件
  Column()
    .width(200)
    .height(200)
    .backgroundColor('#007DFF')
  
  // 绝对定位的上层组件
  Text('定位文本')
    .position({ x: 20, y: 20 })   // 水平偏移20vp、垂直偏移20vp
    .fontColor(Color.White)
}
.width(300)
.height(300)

// { x : 0, y : 0 }时子组件对应在父组件的左上角(零偏移)
层级控制 zIndex

作用:在不改变组件结构的前提下,调整组件的显示层级。

  • 取值为整数数字,数值越大,显示层级越高。

  • 默认值为0

TypeScript 复制代码
Stack() {
  Text('层级1,默认zIndex=0,底层。')
    .width(200)
    .height(200)
    .backgroundColor('#007DFF')
    .zIndex(0)
  
  Text('层级2,zIndex=1,上层。')
    .width(100)
    .height(100)
    .backgroundColor('#FF6B00')
    .zIndex(1)
}

四、常用基础组件

1. 文本组件 Text
  • 用于界面文本内容展示,是最基础的内容组件。

  • 支持丰富的文本样式与展示规则配置。

基础语法
TypeScript 复制代码
Text('文本内容')
核心样式配置
TypeScript 复制代码
Text('鸿蒙ArkUI开发')
  .fontSize(20)   // 字体大小  单位fp
  .fontWeight(FontWeight.Bold)   // 字体粗细  支持枚举、100-900数值
       // 默认400(Normal)  700等同于Bold
  .fontColor(Color.Blue)   // 字体颜色  支持枚举、16进制色值
       // 16进制色值属于字符串 要用引号包裹
  .lineHeight(30)   // 文本行高  控制垂直间距
  .textAlign(TextAlign.Center)   // 文本水平对齐方式
文本溢出处理
  • 超长文本的展示控制

  • textOverflow 必须配合 maxLines 和固定宽度 width 使用,三者缺一不可,否则不生效。

TypeScript 复制代码
Text('这是一段超长的文本内容,用于测试文本溢出省略的效果,超出指定行数后会自动显示省略号')
  .width(200)   // 必须约束宽度 否则文本会无限撑开
  .maxLines(2)   // 限制最大显示行数
  .textOverflow({ overflow: TextOverflow.Ellipsis })   // 溢出显示省略号

溢出模式可选值:

  • TextOverflow.Ellipsis:溢出文本显示省略号

  • TextOverflow.Clip:溢出文本直接裁切(无省略号)

  • TextOverflow.Marquee:文本单行滚动跑马灯效果(maxLines设置无效)

2. 图片组件 Image
  • 用于界面图片展示

  • 支持本地图片、网络图片、SVG图标

  • 可灵活控制缩放与展示效果。

  • SVG图标:svg图标任意放大缩小不失真、可以修改颜色

  • HarmonyOS官方图标库: developer.huawei.com/consumer/cn...

基础语法
TypeScript 复制代码
Image(图片数据源)
网络图片加载
  • 直接传入图片网络地址字符串

  • 必须先申请网络权限,否则无法加载

TypeScript 复制代码
Image('https://example.com/image.jpg')
  .width(200)
  .height(200)
  .objectFit(ImageFit.Cover)   // 图片缩放模式
  • 网络权限配置步骤

(1)打开项目路径 main/module.json5 文件

(2)在 module 节点下添加 requestPermissions 配置:

JSON 复制代码
{
  "requestPermissions": [
    {
      "name": "ohos.permission.INTERNET",
      "reason": "$string:internet_permission_reason",
      "usedScene": {
        "abilities": ["EntryAbility"],
        "when": "inuse"
      }
    }
  ]
}

(3)在 main/resources/base/element/string.json 中添加权限说明:

JSON 复制代码
{
  "name": "internet_permission_reason",
  "value": "用于加载网络图片资源"
}
本地图片/SVG图标引用

(1)本地图片或SVG图标需存放至项目固定路径 main/resources/base/media 目录下

(2)文件名禁止使用中文、空格、特殊符号(无需写文件后缀名)

(3)通过 $r 资源引用语法调用,SVG图标可通过 fillColor 修改颜色。

TypeScript 复制代码
// 本地图片示例:media目录下有一张logo.png
Image($r('app.media.logo'))
  .width(150)
  .height(50)

// SVG图标示例:media目录下有一张ic_back.svg
Image($r('app.media.ic_back'))
  .width(24)
  .height(24)
  .fillColor('#333333')   // 修改SVG图标颜色
  // svg图标文件的命名一般为ic_xxx
图片缩放模式 objectFit
枚举值 核心效果 适用场景
ImageFit.Cover 等比例缩放至铺满容器 不变形、裁切多余部分 封面图、背景图等 需要填满容器的场景
ImageFit.Contain 等比例缩放至完整展示 不变形、容器可能留白 商品图、logo图等 需要完整展示内容的场景
3. 输入框组件 TextInput
  • 用于接收用户输入的文本内容

  • 常用于登录、注册、表单等场景

  • 支持多种输入类型与内容实时监听

基础语法
TypeScript 复制代码
TextInput(参数对象)
  .属性方法()
  .事件回调()
核心用法示例
TypeScript 复制代码
// 用户名输入框(明文)
TextInput({
  placeholder: '请输入用户名'   // 无输入时的占位提示文本
})
.type(InputType.Normal)   // 输入框类型  普通明文输入
.width('100%')
.height(45)

// 密码输入框(密文)
TextInput({
  placeholder: '请输入密码'
})
.type(InputType.Password)   // 密码类型  输入内容自动隐藏
.width('100%')
.height(45)
常用输入类型
类型枚举 适用场景
InputType.Normal 普通文本输入 明文显示 无特殊限制
InputType.Password 密码输入 密文隐藏内容
InputType.Email 邮箱地址输入
InputType.Number 纯数字输入
InputType.NumberDecimal 带小数点的数字输入
InputType.PhoneNumber 手机号输入
InputType.URL 网址链接输入
输入内容实时获取
  • 通过 onChange 事件实时监听用户输入

  • 搭配 @State 状态变量存储输入内容,实现数据双向绑定。

@State响应式状态装饰器,变量值变化时UI会自动刷新。

onChange 输入变化回调 ,用户输入时实时触发,将最新输入值赋值给对应的 @State 变量,实现数据→状态→UI的同步。

TypeScript 复制代码
@Entry
@Component
struct InputDemo {
  // 声明状态变量  存储输入内容
  @State userName: string = ''
  @State password: string = ''

  build() {
    Column({ space: 20 }) {
      // 用户名输入框  绑定状态
      TextInput({ placeholder: '请输入用户名' })
        .type(InputType.Normal)
        .width('100%')
        .height(45)
        .onChange((value: string) => {
          this.userName = value   // 实时赋值给状态变量
        })

      // 密码输入框  绑定状态
      TextInput({ placeholder: '请输入密码' })
        .type(InputType.Password)
        .width('100%')
        .height(45)
        .onChange((value: string) => {
          this.password = value
        })
    }
    .padding(20)
    .width('100%')
    .height('100%')
  }
}
4. 按钮组件 Button
  • 用于响应用户点击操作

  • 是界面交互的核心组件

  • 支持文本按钮、自定义子组件按钮等多种形式

基础语法
TypeScript 复制代码
// 文本按钮
Button('按钮显示文本')
  .属性方法()
  .onClick(() => {
    // 点击按钮执行的业务逻辑
  })

// 自定义子组件按钮
Button() {
  // 自定义按钮内的UI内容
  Row({ space: 8 }) {
    Image($r('app.media.ic_login'))
      .width(20)
      .height(20)
    Text('登录')
  }
}
.onClick(() => {
  // 点击按钮执行的业务逻辑
})
常用样式示例
TypeScript 复制代码
Button('登录')
  .width('100%')
  .height(50)
  .fontSize(18)
  .fontWeight(FontWeight.Medium)
  .backgroundColor('#007DFF')
  .fontColor(Color.White)
  .borderRadius(25)
  .onClick(() => {
    // 点击登录按钮,执行登录逻辑
    console.log('点击了登录按钮')
  })

五、布局容器组件

容器组件是布局的核心,用于控制子组件的排列方式、尺寸约束,是搭建页面骨架的核心能力。

1. 线性布局:Column列布局
  • 垂直方向排列子组件,是页面最常用的根容器。

  • 主轴为垂直方向,交叉轴为水平方向

TypeScript 复制代码
// space参数:控制子组件之间的垂直间距
Column({ space: 20 }) {
  Text('文本1')
  Text('文本2')
  Text('文本3')
}
.justifyContent(FlexAlign.Center)   // 主轴对齐:垂直方向子组件排列
.alignItems(HorizontalAlign.Start)   // 交叉轴对齐:水平方向子组件排列
.width('100%')
.height('100%')
配置项 作用 常用枚举值
space 参数 子组件之间的垂直间距 单位vp
justifyContent 属性 主轴(垂直)对齐方式 FlexAlign.Start 顶部对齐(默认) FlexAlign.Center 垂直居中 FlexAlign.End 底部对齐 FlexAlign.SpaceBetween 上下元素贴边对齐 FlexAlign.SpaceAround 所有元素上下两侧均分间距 FlexAlign.SpaceEvenly 所有间距完全均分
alignItems 属性 交叉轴(水平)对齐方式 HorizontalAlign.Start 居左对齐 HorizontalAlign.Center 水平居中(默认) HorizontalAlign.End 居右对齐
2. 线性布局:Row行布局
  • 水平方向排列子组件,常用于横向排列的标签栏、按钮组、信息行等场景。

  • 主轴为水平方向,交叉轴为垂直方向

TypeScript 复制代码
// space参数:控制子组件之间的水平间距
Row({ space: 10 }) {
  Text('首页')
  Text('分类')
  Text('我的')
}
.justifyContent(FlexAlign.SpaceEvenly)   // 主轴对齐:水平方向子组件排列
.alignItems(VerticalAlign.Center)   // 交叉轴对齐:垂直方向子组件排列
.width('100%')
.height(50)
配置项 作用 常用枚举值
space 参数 子组件之间的水平间距 单位vp
justifyContent 属性 主轴(水平)对齐方式 FlexAlign.Start 居左对齐(默认) FlexAlign.Center 水平居中 FlexAlign.End 居右对齐 FlexAlign.SpaceBetween 左右元素贴边对齐 FlexAlign.SpaceAround 所有元素左右两侧均分间距 FlexAlign.SpaceEvenly 所有间距完全均分
alignItems 属性 交叉轴(垂直)对齐方式 VerticalAlign.Top 居上对齐 VerticalAlign.Center 垂直居中(默认) VerticalAlign.Bottom 居下对齐
3. 自适应权重 layoutWeight
  • 用于实现子组件的自适应伸缩

  • 设置该属性的子组件,会按照权重分配主轴的剩余空间,是适配不同屏幕宽度的核心能力。

核心规则
  • 数字参数为权重份数,剩余空间会按权重比例分配给对应子组件。

  • 固定尺寸的子组件不设置layoutWeight,自适应的子组件设置对应权重。

  • 仅在父容器的主轴方向生效(Column垂直方向生效,Row水平方向生效)。

TypeScript 复制代码
Row({ space: 10 }) {
  // 固定宽度组件
  Image($r('app.media.ic_avatar'))
    .width(40)
    .height(40)
  // 自适应宽度组件  占据剩余所有空间
  Text('用户昵称')
    .layoutWeight(1)
    .fontSize(16)
  // 固定宽度组件
  Text('关注')
    .width(60)
    .height(30)
    .textAlign(TextAlign.Center)
    .backgroundColor('#007DFF')
    .fontColor(Color.White)
    .borderRadius(15)
}
.width('100%')
.padding(20)
4. 弹性布局 Flex
  • 弹性布局是更灵活的线性布局

  • 核心特性是支持子元素换行、自动压缩

  • 适合不规则的多元素排列、标签流等场景

  • 单行单列布局建议优先使用线性布局,线性布局的性能优化更高。

  • 线性布局Column和Row默认情况下是不支持换行的

TypeScript 复制代码
// 语法
Flex(参数对象){
   子组件1
   子组件2
   子组件3
   ......
   子组件n
}
  • 弹性布局Flex又被称为伸缩布局,当子元素的总和溢出父元素时,默认进行压缩显示。

  • Flex默认主轴水平往右、交叉轴垂直往下(与Row相似)

  • 主轴方向 direction : FlexDirection.RowFlexDirection.Column

  • 主轴对齐方式 justifyContent : FlexAlign.枚举

  • 交叉轴对齐方式 alignItems : ItemAlign.枚举

  • Flex布局换行 wrap :FlexWrap.Wrap 换行 、FlexWrap.NoWrap 不换行

TypeScript 复制代码
// 不规则的布局方式只能用FlexWrap来解决
Flex({
   wrap : FlexWrap.Wrap
})
TypeScript 复制代码
// 换行标签流示例
Flex({
  wrap: FlexWrap.Wrap,   // 开启换行 (默认为NoWrap不换行)
  direction: FlexDirection.Row,   // 主轴方向  (默认Row水平方向)
  justifyContent: FlexAlign.Start,   // 主轴对齐
  alignItems: ItemAlign.Center,   // 交叉轴对齐
  space: 10   // 子组件间距
}) {
  Text('鸿蒙开发')
  Text('ArkTS')
  Text('声明式UI')
  Text('组件化开发')
  Text('HarmonyOS NEXT')
  Text('移动端开发')
}
.padding(20)
.width('100%')
5. 层叠布局 Stack
  • 层叠布局用于实现子组件的层叠效果

  • 子组件默认按照代码顺序,后写的覆盖先写的。

  • 支持统一设置对齐方式,比绝对定位更简洁,编码效率更高。

TypeScript 复制代码
// 语法
Stack({
  alignContent : Alignment.Center
}){
  Item1()
  Item2()
  Item3()
  ......
}
// 默认居中Alignment.Center
// ({ alignContent : Alignment.Center }可不写)
// TopStart左上 、Top中上 、TopEnd右上
// Start左 、Center中 、End右
// BottomStart左下 、Bottom中下 、BottomEnd右下
TypeScript 复制代码
// 图片+角标示例
Stack({
  alignContent: Alignment.TopEnd // 子组件默认对齐方式,默认Center居中
}) {
  // 底层图片
  Image($r('app.media.goods_img'))
    .width(120)
    .height(120)
    .borderRadius(8)
    .objectFit(ImageFit.Cover)
  
  // 上层热销角标
  Text('热销')
    .fontSize(12)
    .fontColor(Color.White)
    .backgroundColor('#FF4D4F')
    .padding({ left: 8, right: 8, top: 2, bottom: 2 })
    .borderRadius({ topRight: 8, bottomLeft: 8 })
}
相关推荐
HarmonyOS_SDK1 天前
【FAQ】HarmonyOS SDK 闭源开放能力 —Push Kit
harmonyos
ChinaDragon1 天前
HarmonyOS:ArkWeb在新窗口中打开页面
harmonyos
ChinaDragon1 天前
HarmonyOS:通过组件导航设置标题栏动态显隐及隐藏类型
harmonyos
CHB2 天前
uni-app x 蒸汽模式 性能测试基准报告 Benchmark
uni-app·harmonyos
chenyingjian5 天前
鸿蒙|性能优化-概述与工具使用
harmonyos
二流小码农5 天前
鸿蒙开发:路由组件升级,支持页面一键创建
android·ios·harmonyos
TT_Close5 天前
【Flutter×鸿蒙】debug 包也要签名,这点和 Android 差远了
android·flutter·harmonyos
TT_Close6 天前
【Flutter×鸿蒙】FVM 不认鸿蒙 SDK?4步手动塞进去
flutter·swift·harmonyos
hqk6 天前
鸿蒙项目实战:手把手带你实现 WanAndroid 布局与交互
android·前端·harmonyos