# harmonyos **Repository Path**: jshand/harmonyos ## Basic Information - **Project Name**: harmonyos - **Description**: 鸿蒙学习 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-28 - **Last Updated**: 2026-09-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 环境安装 ## 下载 ## 安装工具 ## 安装模拟器 ### 启动虚拟化的时候有可能出现的问题 请参考https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-emulator-faqs#section214296171615 ![image-20260828161916116](assets/image-20260828161916116.png) ## 解决步骤 **处理步骤** 1. 请先确认CPU型号是否支持虚拟化技术,如果不支持,则无法使用模拟器。 2. 如果CPU支持虚拟化,打开控制面板 > 程序 > 程序和功能 > 启动或关闭Windows功能(Windows11系统中打开系统 > 可选功能 > 相关设置 > 更多Windows功能),检查功能“Hyper-V”、“Windows虚拟机监控程序平台”、“虚拟机平台”是否存在。 - 如果不存在,说明系统未预装Hyper-V,请根据系统版本先安装Hyper-V。 - 如果存在,勾选这三个功能,点击确定并重启电脑。 ![img](assets/zh-cn_image_0000002678154217.png) 3. 若勾选后启动模拟器仍然提示该错误,需要以管理员权限打开命令行窗口执行以下命令,并重启电脑。 ```bash bcdedit /set hypervisorlaunchtype auto ``` 4. 如果按照上述步骤无法解决,打开**任务管理器->性能**,若显示虚拟化已禁用或未开启,则是BIOS中虚拟化没有开启,请根据计算机的主板型号,进入BIOS设置界面,并开启虚拟化功能。 ![img](assets/zh-cn_image_0000002678154207.png) 更多关于Hyper-V安装请参考[在 Windows 上安装 Hyper-V](https://learn.microsoft.com/zh-cn/windows-server/virtualization/hyper-v/get-started/Install-Hyper-V?f=255&MSPPError=-2147217396)和[Hyper-V 系统要求](https://learn.microsoft.com/zh-cn/windows-server/virtualization/hyper-v/host-hardware-requirements)。 # 制作登录界面 ## 创建项目 # **创建项目** ![img](assets/wps1.jpg) ![img](assets/wps2.jpg) ![img](assets/wps3.jpg) 执行 ![img](assets/wps4.jpg) https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-common-components-text-display ![image-20260828144119191](assets/image-20260828144119191.png) 组件 组件是UI的必要元素,形成了在界面中的样子,由框架直接提供的称为**系统组件**,由开发者定义的称为**自定义组件**。系统组件包括按钮、单选框、进度条、文本等。开发者可以通过链式调用的方式设置系统组件的渲染效果。开发者可以将系统组件组合为自定义组件,通过这种方式将页面组件化为一个个独立的UI单元,实现页面不同单元的独立创建、开发和复用,具有更强的工程性。 ## Text Text是文本组件,用于展示用户视图,如显示文章的文字内容。该组件支持绑定自定义文本选择菜单,用户可根据需要选择不同功能。此外,还可以扩展自定义菜单,丰富可用选项,进一步提升用户体验。Span则用于展示行内文本。 ### 通用属性 https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-component-general-attributes - **[基础属性](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/basic-property)** - **[布局与边框](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/layout-property)** - **[视效与模糊](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/visual-effect-property)** - **[交互属性](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/interaction-property)** - **[多态样式](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-polymorphic-style)** - **[弹窗控制](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/popup-property)** - **[无障碍属性](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-accessibility)** - **[模态转场设置](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/transition)** - **[动态属性与自定义](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/attribute-modifier-property)** - **[其他](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/other-property)** ### 设置文本的属性 https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-text - 设置文字的颜色 ``` fontColor(value: ResourceColor): TextAttribute; ``` 需要传递一个颜色的之 | 属性 | 说明 | | :------------- | :--------------------------------------------------- | | decoration | 设置文本装饰线样式及其颜色。 | | font | 设置文本样式。 | | font | 设置文本样式,支持设置字体配置项。 | | fontColor | 设置字体颜色。 | | fontFamily | 设置字体族。 | | fontFeature | 设置文字特性效果,比如数字等宽的特性。 | | fontSize | 设置字体大小。自适应字号生效时,fontSize设置不生效。 | | fontStyle | 设置字体样式。 | | fontWeight | 设置文本的字体粗细。 | | fontWeight | 设置文本字重,支持设置字体配置项。 | | fontVariations | 设置可变字体的属性。**起始版本:** 26.0.0 | | letterSpacing | 设置文本字符间距。 | | shaderStyle | 设置文本渐变或纯色效果。 | | textCase | 设置文本大小写。 | | textShadow | 设置文字阴影效果。 | **文本溢出、断行与折行** | 属性 | 说明 | | :------------------ | :-------------------------------------------------- | | ellipsisMode | 设置省略位置。 | | lineBreakStrategy | 设置折行规则。 | | marqueeOptions | 设置文本跑马灯模式的配置项。 | | textOverflow | 设置文本超长时的显示方式。 | | wordBreak | 设置断行规则。 | | punctuationOverflow | 设置是否启用行尾标点符号悬挂。**起始版本:** 26.0.0 | 行与段落 | enableAutoSpacing | 设置是否开启中文与西文的自动间距。 | | --------------------- | ------------------------------------------------------------ | | lineHeight | 设置文本的行高。 | | lineHeightMultiple | 设置文本的行高倍数。 | | lineSpacing | 设置文本的行间距。 | | lineSpacing | 设置文本的行间距。当不配置LineSpacingOptions时,首行上方和尾行下方默认会有行间距。当与lineHeightMultiple同时设置且lineHeightMultiple使用有效值时,仅lineHeightMultiple生效。 | | maxLineHeight | 设置文本的最大行高。 | | maxLines | 设置文本的最大行数。 | | minLineHeight | 设置文本的最小行高。 | | minLines | 设置文本显示的最小行数。 | | optimizeTrailingSpace | 优化行尾空格。 | | textIndent | 设置首行文本缩进。 | | tailIndents | 设置文本尾部缩进。**起始版本:** 26.0.0 | **字体自适应** | 属性 | 说明 | | :------------------- | :--------------------------------- | | heightAdaptivePolicy | 设置文本自适应布局调整字号的方式。 | | maxFontScale | 设置文本最大的字体缩放倍数。 | | maxFontSize | 设置文本最大显示字号。 | | minFontScale | 设置文本最小的字体缩放倍数。 | | minFontSize | 设置文本最小显示字号。 | **文本选择与复制** | 属性 | 说明 | | :---------------------- | :------------------------------- | | caretColor | 设置文本组件选中区域手柄颜色。 | | copyOption | 设置组件是否支持文本可复制粘贴。 | | draggable | 设置选中文本拖拽效果。 | | selectedBackgroundColor | 设置文本选中底板颜色。 | | selection | 设置选中区域。 | | textSelectable | 设置是否支持文本可选择、可获焦。 | **文本识别** | 属性 | 说明 | | :------------------------- | :----------------------------------------------------------- | | dataDetectorConfig | 设置文本识别配置。 | | enableDataDetector | 设置是否进行文本实体识别,可自动识别电话号码、网址、邮箱、地址、日期等。 | | enableSelectedDataDetector | 设置是否对选中文本进行实体识别。 | **自定义菜单** | 属性 | 说明 | | :---------------- | :--------------------- | | bindSelectionMenu | 设置自定义选择菜单。 | | editMenuOptions | 设置自定义菜单扩展项。 | **其他功能** | 属性 | 说明 | | :---------------------- | :------------------------------------------------ | | contentTransition | 文本动效属性。 | | enableHapticFeedback | 设置是否开启触控反馈。 | | incrementalUpdatePolicy | 设置文本渲染的增量更新策略。**起始版本:** 26.0.0 | | privacySensitive | 设置是否支持卡片敏感隐私信息。 | 查找属性值的类型 ### background CTRL+鼠标左键 ## Image ``` Image('图片的资源地址') Image($r('app.media.startIcon')).width(50).height(50) ``` $r(): 函数 是引用资源的意思 ![image-20260828150126798](assets/image-20260828150126798.png) ## Blank 空白填充组件,在容器主轴方向上,空白填充组件具有自动填充容器空余部分的能力。仅当父组件为[Row](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-row)/[Column](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-column)/[Flex](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-flex)时生效。 说明 该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 ## 使用iconfont ![image-20260828151842955](assets/image-20260828151842955.png) ![image-20260828151917477](assets/image-20260828151917477.png) ![image-20260828151935236](assets/image-20260828151935236.png) 资源文件命名不能出现 特殊字符, [a-zA-Z0-9_]. ### 下载gitee 上的图片 ![image-20260828153155202](assets/image-20260828153155202.png) ![image-20260828153248964](assets/image-20260828153248964.png) ![image-20260828153313466](assets/image-20260828153313466.png) D:\workspace\app\entry\src\main\resources\base\media ![image-20260828160111359](assets/image-20260828160111359.png) ```ts @Entry @Component struct Index { @State message: string = 'Hello 金山'; //构建页面组件 build() { Column() { Row() { Image($r('app.media.arrow')).width(30).height(30) Blank() Text("登录") Blank() Text("注册 ").fontColor('#FF6E2D') } .width('100%') // .background(Color.Gray) Text("广厦商城").fontSize(30).fontColor("#FB6D34").margin({ top: 100, }) Text("HarmonOS 教学实战") // 颜色 .fontColor(Color.Grey) //字体 .fontFamily("宋体") //大小 .fontSize(12) Row() { Text("验证码登录") // 颜色 .fontColor('#FB6D34') //字体 .fontFamily("宋体") //大小 .fontSize(12) Text("|") // 颜色 .fontColor(Color.Grey) //字体 .fontFamily("宋体") //大小 .fontSize(12) Text("密码登录") // 颜色 .fontColor(Color.Grey) //字体 .fontFamily("宋体") //大小 .fontSize(12) } .margin({ top: 100 }) } } } ``` # ArkTS - 定义变量 ```ts let age:number = 18 let name:string = '' let success:boolean = true ``` ## 函数 ## 3.3 高级类型 ### 3.3.1 数组(Array) **定义方式**: ```typescript // 方式1:Array<类型> let arr1: Array = [1, 2, 3] // 方式2:类型[] let arr2: string[] = ['a', 'b', 'c'] // 方式3:空数组(需要类型推断) let arr3 = [1, 2, 3] // number[] // 方式4:指定长度 let arr4: number[] = new Array(5) // [undefined, undefined, undefined, undefined, undefined] let arr5: number[] = [] // 空数组 ``` **常用操作**: ```typescript let fruits: string[] = ['Apple', 'Banana', 'Orange'] // 访问元素 fruits[0] // 'Apple' fruits.length // 3 // 添加元素 fruits.push('Grape') // 末尾添加,返回新长度 fruits.unshift('Mango') // 头部添加,返回新长度 // 删除元素 fruits.pop() // 末尾删除,返回删除的元素 fruits.shift() // 头部删除,返回删除的元素 fruits.splice(1, 1) // 删除指定位置元素 // 查找元素 fruits.indexOf('Banana') // 1 fruits.includes('Apple') // true fruits.find(f => f === 'Apple') // 'Apple' // 切片 fruits.slice(0, 2) // ['Apple', 'Banana'] // 合并 let moreFruits = ['Grape', 'Kiwi'] fruits.concat(moreFruits) // ['Apple', 'Banana', 'Orange', 'Grape', 'Kiwi'] ``` **遍历数组**: ```typescript let numbers: number[] = [1, 2, 3, 4, 5] // for 循环 for (let i = 0; i < numbers.length; i++) { console.log(numbers[i]) } // for...of 循环(推荐) for (let num of numbers) { console.log(num) } // forEach 方法 numbers.forEach((num, index) => { console.log(`${index}: ${num}`) }) ``` ### 3.3.2 元组(Tuple) 元组是固定长度和类型的数组: ```typescript // 定义元组 let person: [string, number, boolean] = ['Alice', 25, true] // 访问元素 person[0] // 'Alice' person[1] // 25 // 解构赋值 let [name, age, isStudent] = person // 可选元素 let optional: [string, number?] = ['Hello'] optional[1] // undefined // 可变元素 let mixed: [string, ...number[]] = ['a', 1, 2, 3] ``` ### 3.3.3 枚举(Enum) ```typescript // 数字枚举(默认) enum Color { Red, // 0 Green, // 1 Blue // 2 } let c1: Color = Color.Red let c2: number = Color.Green // 1 // 字符串枚举 enum Status { Success = 'success', Error = 'error', Loading = 'loading' } let s1: Status = Status.Success // 异构枚举(混合) enum BooleanLike { No = 0, Yes = 'yes' } // 常量枚举(编译时内联) const enum Direction { Up = 'UP', Down = 'DOWN' } let d: Direction = Direction.Up // 编译后直接替换为 'UP' // 反向映射 enum Animal { Dog, Cat } let dogName: string = Animal[0] // 'Dog' ``` ### 3.3.4 对象类型(Object) ```typescript // 方式1:interface 接口 interface User { name: string age: number email?: string // 可选属性 readonly id: number // 只读属性 } let user: User = { name: 'Alice', age: 25, id: 1 } // 方式2:type 别名 type Point = { x: number y: number } let point: Point = { x: 0, y: 0 } // 方式3:匿名对象类型 let config: { host: string port: number ssl: boolean } = { host: 'localhost', port: 8080, ssl: true } ``` ### 3.3.5 联合类型(Union) ```typescript // 基础联合类型 let id: string | number = '123' id = 456 // 也可以是数字 // 多类型联合 type StringOrNumber = string | number type BoolOrString = boolean | string // 函数参数联合 function format(value: string | number): string { if (typeof value === 'string') { return value.toUpperCase() } else { return value.toFixed(2) } } // 可辨识联合(Tagged Union) interface Cat { kind: 'cat' meow: () => void } interface Dog { kind: 'dog' bark: () => void } type Animal2 = Cat | Dog function speak(animal: Animal2) { switch (animal.kind) { case 'cat': animal.meow() break case 'dog': animal.bark() break } } ``` ### 3.3.6 交叉类型(Intersection) ```typescript interface A { a: string } interface B { b: number } // 交叉类型 type AB = A & B let obj: AB = { a: 'hello', b: 123 } // 混入示例 type NamedPerson = { name: string } type AgedPerson = { age: number } type Person = NamedPerson & AgedPerson let person: Person = { name: 'Alice', age: 25 } ``` ### 3.3.7 类型别名(Type Alias) ```typescript // 基本用法 type ID = string | number type Callback = () => void type Pair = [T, T] let userId: ID = '12345' let callbackFn: Callback = () => console.log('called') let pair: Pair = ['a', 'b'] // 条件类型 type NonNullable = T extends null | undefined ? never : T type A2 = NonNullable // string type B2 = NonNullable // number // 映射类型 type Readonly = { readonly [P in keyof T]: T[P] } interface User2 { name: string age: number } type ReadonlyUser = Readonly // { readonly name: string; readonly age: number } ``` ### 3.3.8 泛型(Generic) ```typescript // 泛型函数 function identity(arg: T): T { return arg } identity('hello') // 'hello' identity(123) // 123(类型推断) // 泛型接口 interface Container { value: T getValue(): T } let numContainer: Container = { value: 123, getValue() { return this.value } } // 泛型类 class Box { content: T constructor(content: T) { this.content = content } getContent(): T { return this.content } } let box = new Box('books') box.getContent() // 'books' // 泛型约束 interface HasLength { length: number } function logLength(arg: T): number { return arg.length } logLength('hello') // 5 logLength([1, 2, 3]) // 3 logLength({ length: 10 }) // 10 // keyof 约束 function getProperty(obj: T, key: K): T[K] { return obj[key] } let user3 = { name: 'Alice', age: 25 } getProperty(user3, 'name') // 'Alice' getProperty(user3, 'age') // 25 ``` --- ## # 创建页面 ![image-20260911145148604](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20260911145148604.png) ![image-20260911145221981](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20260911145221981.png) ## 使用路由器 跳转页面 ``` // 系统内置的 路由 import { router } from "@kit.ArkUI"; // router.push({url:'pages/Home'}) router.replace({url:'pages/Home'}) ``` [组件导航和页面路由概述-设置组件导航和页面路由-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-introduction) 常见的组件 # 第4章 ArkUI 基础与组件 ## 4.1 ArkUI 概述 ### 4.1.1 什么是 ArkUI ArkUI(方舟 UI 框架)是一套构建分布式应用界面的**声明式 UI 开发框架**。它使用简洁的 UI 信息语法、丰富的 UI 组件、实时界面预览工具,提升应用界面开发效率。 ### 4.1.2 声明式 UI 特点 ``` ┌─────────────────────────────────────────────────────────┐ │ 传统命令式 UI │ │ "如何做" - 描述操作步骤 │ │ 1. 创建按钮 │ │ 2. 设置按钮文本 │ │ 3. 设置按钮位置 │ │ 4. 添加点击监听 │ │ 5. 将按钮添加到容器 │ └─────────────────────────────────────────────────────────┘ VS ┌─────────────────────────────────────────────────────────┐ │ 声明式 UI │ │ "做什么" - 描述最终结果 │ │ Button('点击') │ │ .text('点击') │ │ .position({x: 100, y: 200}) │ │ .onClick(() => {}) │ └─────────────────────────────────────────────────────────┘ ``` ### 4.1.3 页面结构 ```typescript // ArkUI 页面的基本结构 @Entry // 页面入口装饰器 @Component // 组件装饰器 struct Index { // 页面组件(必须用 struct 声明) @State message: string = 'Hello' // 状态变量 build() { // build() 方法返回 UI 描述 // 返回的 UI 必须是单个根容器 Column() { Text(this.message) } .width('100%') .height('100%') } } ``` --- ## 4.2 基础组件概述 ### 4.2.1 组件分类 ArkUI 组件主要分为以下几类: | 类别 | 组件 | 说明 | | ------------ | ------------------------------- | ---------------- | | **基础组件** | Text、Image、Button | 最基本的 UI 元素 | | **输入组件** | TextInput、TextArea、Slider | 用户输入类 | | **选择组件** | Checkbox、Radio、Switch、Toggle | 选择类 | | **进度组件** | Progress、LoadingProgress | 进度显示类 | | **容器组件** | Column、Row、Stack、Flex | 布局容器 | | **列表组件** | List、Grid、Swiper | 列表类 | | **导航组件** | Tabs、Navigation | 导航类 | --- ## 4.3 文本组件(Text) ### 4.3.1 基本用法 **语法**: ```typescript Text(content: string | Resource) ``` **示例**: ```typescript @Entry @Component struct TextExample { build() { Column({ space: 20 }) { // 基本文本 Text('基本文本') // 字符串变量 Text(this.message) // 使用资源引用 Text($r('app.string.app_name')) } } } ``` ### 4.3.2 文本样式属性 | 属性 | 类型 | 说明 | 示例 | | -------------- | ------------------- | -------- | -------------------------------------------------------- | | `fontSize` | number / Resource | 字体大小 | `.fontSize(16)` / `.fontSize($r('app.float.text_size'))` | | `fontColor` | Color / Resource | 字体颜色 | `.fontColor('#333333')` / `.fontColor(Color.Blue)` | | `fontWeight` | number / FontWeight | 字重 | `.fontWeight(FontWeight.Bold)` / `.fontWeight(600)` | | `fontStyle` | FontStyle | 字体样式 | `.fontStyle(FontStyle.Italic)` | | `fontFamily` | string / Resource | 字体族 | `.fontFamily('HarmonyOS Sans')` | | `textAlign` | TextAlign | 文本对齐 | `.textAlign(TextAlign.Center)` | | `lineHeight` | number / Resource | 行高 | `.lineHeight(24)` | | `maxLines` | number | 最大行数 | `.maxLines(2)` | | `textOverflow` | TextOverflow | 文本溢出 | `.textOverflow({ overflow: TextOverflow.Ellipsis })` | **示例**: ```typescript @Entry @Component struct TextStyleExample { build() { Column({ space: 15 }) { // 默认文本 Text('默认文本') // 大号加粗文本 Text('大号加粗') .fontSize(24) .fontWeight(FontWeight.Bold) // 彩色斜体文本 Text('彩色斜体') .fontSize(18) .fontColor('#FF6B6B') .fontStyle(FontStyle.Italic) // 带行高的文本 Text('这是一段较长的文本内容,需要设置行高来改善阅读体验。这是一段较长的文本内容,需要设置行高来改善阅读体验。') .fontSize(14) .lineHeight(22) .textAlign(TextAlign.Start) // 居中对齐 Text('居中文本') .textAlign(TextAlign.Center) .width('100%') // 右对齐 Text('右对齐文本') .textAlign(TextAlign.End) .width('100%') } .width('100%') .padding(20) } } ``` ### 4.3.3 文本溢出处理 ```typescript @Entry @Component struct TextOverflowExample { @State text: string = '这是一段很长的文本内容,当超过容器的宽度时,应该显示省略号来表示还有更多内容。' build() { Column({ space: 20 }) { // 省略号(末尾) Text('省略号末尾') .fontSize(14) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) // 省略号(中间)- 需要配合 marquee 或自定义实现 Text('省略号中间') .fontSize(14) .maxLines(1) .textOverflow({ overflow: TextOverflow.Middle }) // 省略号(开头) Text('省略号开头') .fontSize(14) .maxLines(1) .textOverflow({ overflow: TextOverflow.Clip }) // 自定义省略符 Text('自定义省略符...') .fontSize(14) .maxLines(1) } .width('100%') .padding(20) } } ``` ### 4.3.4 文本装饰 ```typescript @Entry @Component struct TextDecorationExample { build() { Column({ space: 20 }) { // 下划线 Text('下划线文本') .decoration({ type: TextDecorationType.Underline, color: '#333333' }) // 删除线 Text('删除线文本') .decoration({ type: TextDecorationType.LineThrough, color: '#FF6B6B' }) // 上划线 Text('上划线文本') .decoration({ type: TextDecorationType.Overline, color: '#4ECDC4' }) // 组合装饰 Text('下划线 + 删除线') .decoration({ type: TextDecorationType.Underline | TextDecorationType.LineThrough, color: '#333333' }) } .width('100%') .padding(20) } } ``` ### 4.3.5 文本装饰器(Span) **作用**:在同一个 Text 组件中实现不同样式 **语法**: ```typescript Text() { Span('文本1') .fontSize(16) .foregroundColor('#333333') Span('文本2') .fontSize(20) .foregroundColor('#FF6B6B') } ``` **示例**: ```typescript @Entry @Component struct SpanExample { build() { Column({ space: 20 }) { // 混合样式文本 Text() { Span('红色') .fontColor('#FF6B6B') .fontSize(20) Span(' + ') .fontColor('#333333') Span('蓝色') .fontColor('#4ECDC4') .fontSize(24) .fontWeight(FontWeight.Bold) Span(' 文本') .fontColor('#333333') } .fontSize(16) // 富文本链接 Text() { Span('点击') .fontColor('#1890FF') .onClick(() => { console.info('点击了链接') }) Span('这里') .fontColor('#1890FF') .underline({ color: '#1890FF' }) .onClick(() => { console.info('点击了这里') }) Span('了解更多') .fontColor('#666666') } .fontSize(14) .padding(10) .backgroundColor('#F5F5F5') .borderRadius(8) // 价格显示 Text() { Span('¥') .fontSize(14) Span('99.00') .fontSize(24) .fontWeight(FontWeight.Bold) .fontColor('#FF6B6B') } } .width('100%') .padding(20) } } ``` --- ## 4.4 按钮组件(Button) ### 4.4.1 基本用法 **语法**: ```typescript Button(content?: string | Resource, options?: { type?: ButtonType, stateEffect?: boolean }) ``` **按钮类型**: | 类型 | 说明 | 圆角 | | -------------------- | -------- | ---------- | | `ButtonType.Normal` | 普通按钮 | 0 | | `ButtonType.Capsule` | 胶囊按钮 | 高度的一半 | | `ButtonType.Circle` | 圆形按钮 | 50% | **示例**: ```typescript @Entry @Component struct ButtonExample { build() { Column({ space: 20 }) { // 普通按钮 Button('普通按钮') // 胶囊按钮 Button('胶囊按钮', { type: ButtonType.Capsule }) // 圆形按钮 Button('圆', { type: ButtonType.Circle }) .width(50) .height(50) // 带图标按钮 Button('删除', { type: ButtonType.Normal, stateEffect: true }) } .width('100%') .padding(20) } } ``` ### 4.4.2 按钮样式属性 | 属性 | 类型 | 说明 | 示例 | | ----------------- | ----------------- | -------- | ----------------------------------- | | `type` | ButtonType | 按钮类型 | `.type(ButtonType.Capsule)` | | `stateEffect` | boolean | 点击效果 | `.stateEffect(false)` | | `backgroundColor` | Color / Resource | 背景色 | `.backgroundColor('#FF6B6B')` | | `fontColor` | Color / Resource | 字体颜色 | `.fontColor('#FFFFFF')` | | `fontSize` | number / Resource | 字体大小 | `.fontSize(16)` | | `fontWeight` | FontWeight | 字重 | `.fontWeight(FontWeight.Medium)` | | `borderRadius` | number / Resource | 圆角 | `.borderRadius(8)` | | `width` | Length | 宽度 | `.width('100%')` | | `height` | Length | 高度 | `.height(44)` | | `padding` | Padding / Length | 内边距 | `.padding({ left: 20, right: 20 })` | **示例**: ```typescript @Entry @Component struct ButtonStyleExample { build() { Column({ space: 20 }) { // 自定义颜色按钮 Button('红色按钮') .type(ButtonType.Normal) .backgroundColor('#FF6B6B') .fontColor('#FFFFFF') .borderRadius(8) // 大按钮 Button('大按钮') .type(ButtonType.Normal) .width('100%') .height(56) .fontSize(18) .borderRadius(28) // 胶囊按钮组 Row({ space: 10 }) { Button('是', { type: ButtonType.Capsule }) .backgroundColor('#4CAF50') .fontColor('#FFFFFF') Button('否', { type: ButtonType.Capsule }) .backgroundColor('#F44336') .fontColor('#FFFFFF') Button('取消', { type: ButtonType.Capsule }) .backgroundColor('#9E9E9E') .fontColor('#FFFFFF') } .width('100%') // 禁用状态 Button('禁用按钮') .enabled(false) .opacity(0.5) // 无点击效果 Button('无效果') .stateEffect(false) } .width('100%') .padding(20) } } ``` ### 4.4.3 按钮点击事件 ```typescript @Entry @Component struct ButtonClickExample { @State count: number = 0 @State buttonText: string = '点击我' build() { Column({ space: 20 }) { Text(`计数: ${this.count}`) Button(this.buttonText) .onClick((event: ClickEvent) => { this.count++ console.info('按钮被点击') console.info(`点击坐标: x=${event.x}, y=${event.y}`) }) .onTouch((event: TouchEvent) => { console.info(`触摸状态: ${event.type}`) }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } } ``` ### 4.4.4 带图标按钮 ```typescript @Entry @Component struct IconButtonExample { build() { Column({ space: 20 }) { // 使用 Row 实现图标+文字 Button({ type: ButtonType.Capsule }) { Row({ space: 8 }) { Text('+') .fontSize(20) .fontWeight(FontWeight.Bold) Text('添加') .fontSize(16) } } .backgroundColor('#1890FF') .height(40) // 使用 SymbolGlyph 图标 Button('', { type: ButtonType.Circle }) { SymbolGlyph($r('sys.symbol.ohos_trash')) .fontSize(24) .fontColor('#FFFFFF') } .width(50) .height(50) .backgroundColor('#F44336') // 符号图标按钮组 Row({ space: 15 }) { Button('', { type: ButtonType.Circle }) { SymbolGlyph($r('sys.symbol.ohos_append')) .fontSize(20) .fontColor('#FFFFFF') } .width(44) .height(44) .backgroundColor('#4CAF50') Button('', { type: ButtonType.Circle }) { SymbolGlyph($r('sys.symbol.ohos_edit')) .fontSize(20) .fontColor('#FFFFFF') } .width(44) .height(44) .backgroundColor('#2196F3') Button('', { type: ButtonType.Circle }) { SymbolGlyph($r('sys.symbol.ohos_trash')) .fontSize(20) .fontColor('#FFFFFF') } .width(44) .height(44) .backgroundColor('#F44336') } } .width('100%') .padding(20) .justifyContent(FlexAlign.Center) } } ``` --- ## 4.5 输入组件 ### 4.5.1 单行输入框(TextInput) **语法**: ```typescript TextInput(options?: { placeholder?: ResourceStr, text?: ResourceStr, controller?: TextInputController }) ``` **示例**: ```typescript @Entry @Component struct TextInputExample { @State text: string = '' controller: TextInputController = new TextInputController() build() { Column({ space: 20 }) { // 基本输入框 TextInput({ placeholder: '请输入用户名' }) .onChange((value: string) => { this.text = value }) // 带默认值 TextInput({ text: 'admin' }) .onChange((value: string) => { console.info(`输入内容: ${value}`) }) // 密码输入 TextInput({ placeholder: '请输入密码' }) .type(InputType.Password) .onChange((value: string) => { console.info(`密码: ${value}`) }) // 数字输入 TextInput({ placeholder: '请输入手机号' }) .type(InputType.PhoneNumber) .onChange((value: string) => { console.info(`手机号: ${value}`) }) // 邮箱输入 TextInput({ placeholder: '请输入邮箱' }) .type(InputType.Email) .onChange((value: string) => { console.info(`邮箱: ${value}`) }) // 显示输入内容 Text(`输入的内容: ${this.text}`) } .width('100%') .padding(20) } } ``` **TextInput 样式属性**: | 属性 | 类型 | 说明 | 示例 | | ------------------ | ----------- | ---------- | -------------------------------- | | `placeholder` | ResourceStr | 占位符 | `.placeholder('请输入')` | | `text` | ResourceStr | 绑定文本 | `.text('默认值')` | | `type` | InputType | 输入类型 | `.type(InputType.Password)` | | `placeholderColor` | Color | 占位符颜色 | `.placeholderColor('#999999')` | | `placeholderFont` | Font | 占位符字体 | `.placeholderFont({ size: 14 })` | | `caretColor` | Color | 光标颜色 | `.caretColor('#1890FF')` | | `maxLength` | number | 最大长度 | `.maxLength(100)` | | `copyOption` | CopyOptions | 复制选项 | `.copyOptions(CopyOptions.None)` | | `showPasswordIcon` | boolean | 密码图标 | `.showPasswordIcon(false)` | | `borderRadius` | Length | 圆角 | `.borderRadius(8)` | | `backgroundColor` | Color | 背景色 | `.backgroundColor('#F5F5F5')` | | `fontColor` | Color | 字体颜色 | `.fontColor('#333333')` | ### 4.5.2 多行输入框(TextArea) **语法**: ```typescript TextArea(options?: { placeholder?: ResourceStr, text?: ResourceStr, controller?: TextAreaController }) ``` **示例**: ```typescript @Entry @Component struct TextAreaExample { @State content: string = '' @State remainingChars: number = 200 build() { Column({ space: 20 }) { // 基本多行输入 TextArea({ placeholder: '请输入简介' }) .width('100%') .height(120) .onChange((value: string) => { this.content = value this.remainingChars = 200 - value.length }) // 字数统计 Row() { Text(`还可以输入 ${this.remainingChars} 字符`) .fontSize(12) .fontColor(this.remainingChars < 20 ? '#FF6B6B' : '#999999') } .width('100%') .justifyContent(FlexAlign.End) // 限制行数 TextArea({ placeholder: '最多显示3行' }) .width('100%') .maxLines(3) // 禁用状态 TextArea({ text: '禁用状态,无法输入' }) .enabled(false) .opacity(0.6) // 只读状态 TextArea({ text: '只读状态' }) .copyOptions(CopyOptions.LocalDevice) } .width('100%') .padding(20) } } ``` **TextArea 样式属性**: | 属性 | 类型 | 说明 | 示例 | | ------------------ | ----------- | ---------- | ------------------------------ | | `placeholder` | ResourceStr | 占位符 | `.placeholder('请输入')` | | `text` | ResourceStr | 绑定文本 | `.text('默认值')` | | `placeholderColor` | Color | 占位符颜色 | `.placeholderColor('#999999')` | | `caretColor` | Color | 光标颜色 | `.caretColor('#1890FF')` | | `maxLines` | number | 最大行数 | `.maxLines(5)` | | `maxLength` | number | 最大字符数 | `.maxLength(500)` | | `minLines` | number | 最小行数 | `.minLines(3)` | | `borderRadius` | Length | 圆角 | `.borderRadius(8)` | --- ## 4.6 选择组件 ### 4.6.1 复选框(Checkbox) **语法**: ```typescript Checkbox(options?: { name?: string }) ``` **示例**: ```typescript @Entry @Component struct CheckboxExample { @State selectedFruits: Set = new Set() build() { Column({ space: 15 }) { Text('选择你喜欢的水果') // 苹果 Checkbox({ name: 'apple' }) .selectable(true) .onChange((isChecked: boolean) => { if (isChecked) { this.selectedFruits.add('apple') } else { this.selectedFruits.delete('apple') } }) Row() { Checkbox({ name: 'banana' }) .onChange((isChecked: boolean) => { if (isChecked) { this.selectedFruits.add('banana') } else { this.selectedFruits.delete('banana') } }) Text('香蕉') } Row() { Checkbox({ name: 'orange' }) .onChange((isChecked: boolean) => { if (isChecked) { this.selectedFruits.add('orange') } else { this.selectedFruits.delete('orange') } }) Text('橙子') } // 自定义样式 Checkbox({ name: 'grape' }) .selectedColor('#4ECDC4') // 选中颜色 .shape(CheckboxShape.Circle) // 圆形 .onChange((isChecked: boolean) => { console.info(`葡萄: ${isChecked}`) }) Text(`已选择: ${Array.from(this.selectedFruits).join(', ')}`) .fontSize(14) .fontColor('#666666') } .width('100%') .padding(20) } } ``` ### 4.6.2 单选框(Radio) **语法**: ```typescript Radio(options?: { value?: string, group?: string }) ``` **示例**: ```typescript @Entry @Component struct RadioExample { @State selectedGender: string = 'male' build() { Column({ space: 20 }) { Text('选择性别') // 男 Radio({ value: 'male', group: 'gender' }) .checked(true) .onChange((isChecked: boolean) => { if (isChecked) { this.selectedGender = 'male' } }) Text('男') // 女 Radio({ value: 'female', group: 'gender' }) .onChange((isChecked: boolean) => { if (isChecked) { this.selectedGender = 'female' } }) Text('女') // 未知 Radio({ value: 'unknown', group: 'gender' }) .onChange((isChecked: boolean) => { if (isChecked) { this.selectedGender = 'unknown' } }) Text('未知') Text(`选择的性别: ${this.selectedGender}`) } .width('100%') .padding(20) } } ``` ### 4.6.3 开关(Switch) **语法**: ```typescript Switch() ``` **示例**: ```typescript @Entry @Component struct SwitchExample { @State isDarkMode: boolean = false @State isWifi: boolean = true @State isBluetooth: boolean = false build() { Column({ space: 15 }) { // 深色模式开关 Row() { Text('深色模式') Switch({ isOn: this.isDarkMode }) .onChange((isOn: boolean) => { this.isDarkMode = isOn console.info(`深色模式: ${isOn}`) }) } .width('100%') .justifyContent(FlexAlign.SpaceBetween) // WiFi 开关 Row() { Text('WiFi') Switch({ isOn: this.isWifi }) .onChange((isOn: boolean) => { this.isWifi = isOn }) } .width('100%') .justifyContent(FlexAlign.SpaceBetween) // 蓝牙开关 Row() { Text('蓝牙') Switch({ isOn: this.isBluetooth }) .onChange((isOn: boolean) => { this.isBluetooth = isOn }) } .width('100%') .justifyContent(FlexAlign.SpaceBetween) Divider() // 自定义颜色 Switch({ isOn: true }) .selectedColor('#4ECDC4') // 选中颜色 .switchPointColor('#FFFFFF') // 滑块颜色 // 禁用状态 Switch({ isOn: false }) .enabled(false) .opacity(0.5) } .width('100%') .padding(20) } } ``` ### 4.6.4 切换组件(Toggle) **语法**: ```typescript Toggle(options?: { type: ToggleType, isOn?: boolean }) ``` | ToggleType | 说明 | | --------------------- | ---------- | | `ToggleType.Checkbox` | 复选框样式 | | `ToggleType.Switch` | 开关样式 | | `ToggleType.Button` | 按钮样式 | **示例**: ```typescript @Entry @Component struct ToggleExample { @State isChecked: boolean = false @State isToggleOn: boolean = true build() { Column({ space: 20 }) { // Checkbox 样式 Toggle({ type: ToggleType.Checkbox, isOn: this.isChecked }) .onChange((isOn: boolean) => { this.isChecked = isOn }) Text(`复选框状态: ${this.isChecked}`) // Switch 样式 Toggle({ type: ToggleType.Switch, isOn: this.isToggleOn }) .onChange((isOn: boolean) => { this.isToggleOn = isOn }) Text(`开关状态: ${this.isToggleOn}`) // Button 样式 Toggle({ type: ToggleType.Button, isOn: this.isChecked }) { Text(this.isChecked ? '已启用' : '已禁用') } .onChange((isOn: boolean) => { this.isChecked = isOn }) // 自定义样式 Toggle({ type: ToggleType.Switch, isOn: true }) { } .selectedColor('#4ECDC4') .switchPointColor('#FFFFFF') } .width('100%') .padding(20) } } ``` --- ## 4.7 滑块组件(Slider) ### 4.7.1 基本用法 **语法**: ```typescript Slider(options?: { value?: number, min?: number, max?: number, step?: number, direction?: Axis, controller?: SliderController }) ``` **示例**: ```typescript @Entry @Component struct SliderExample { @State value: number = 50 @State volume: number = 30 @State brightness: number = 80 build() { Column({ space: 30 }) { // 基本滑块 Column() { Text(`基本滑块值: ${this.value}`) Slider({ value: this.value, min: 0, max: 100, step: 1, style: SliderStyle.OutSet }) .blockColor('#1890FF') .trackColor('#E0E0E0') .selectedColor('#1890FF') .showTips(true) .onChange((value: number) => { this.value = value }) } // 音量滑块 Column() { Row() { Text('音量') Text(`${this.volume}%`) } .width('100%') .justifyContent(FlexAlign.SpaceBetween) Slider({ value: this.volume, min: 0, max: 100, step: 5, direction: Axis.Horizontal }) .blockColor('#4ECDC4') .selectedColor('#4ECDC4') .showTips(true) .onChange((value: number) => { this.volume = value }) } // 亮度滑块 Column() { Row() { Text('亮度') Text(`${this.brightness}%`) } .width('100%') .justifyContent(FlexAlign.SpaceBetween) Slider({ value: this.brightness, min: 0, max: 100, step: 1, direction: Axis.Horizontal }) .blockColor('#FFD93D') .selectedColor('#FFD93D') .showTips(true) .onChange((value: number) => { this.brightness = value }) } // 禁用状态 Slider({ value: 50, min: 0, max: 100 }) .enabled(false) .opacity(0.5) } .width('100%') .padding(20) } } ``` ### 4.7.2 Slider 属性详解 | 属性 | 类型 | 说明 | 示例 | | --------------- | ------------- | ------------ | ----------------------------- | | `value` | number | 当前值 | `.value(50)` | | `min` | number | 最小值 | `.min(0)` | | `max` | number | 最大值 | `.max(100)` | | `step` | number | 步进值 | `.step(5)` | | `direction` | Axis | 方向 | `.direction(Axis.Horizontal)` | | `style` | SliderStyle | 样式 | `.style(SliderStyle.OutSet)` | | `blockColor` | Color | 滑块颜色 | `.blockColor('#1890FF')` | | `blockSize` | number | 滑块大小 | `.blockSize(20)` | | `trackColor` | Color | 轨道颜色 | `.trackColor('#E0E0E0')` | | `selectedColor` | Color | 选中颜色 | `.selectedColor('#1890FF')` | | `showTips` | boolean | 显示数值提示 | `.showTips(true)` | | `showTick` | boolean | 显示刻度 | `.showTick(true)` | | `tickMarks` | TickMarkStyle | 刻度样式 | `.tickMarks({ count: 5 })` | --- ## 4.8 进度组件 ### 4.8.1 线性进度条(Progress) **语法**: ```typescript Progress(options: { value: number, total?: number, type?: ProgressType }) ``` | ProgressType | 说明 | | ----------------------- | -------------------- | | `ProgressType.Linear` | 线性进度条 | | `ProgressType.Circular` | 圆形进度条 | | `ProgressType.Eclipse` | 月食进度条 | | `ProgressType.Ring` | 环形进度条(带动画) | **示例**: ```typescript @Entry @Component struct ProgressExample { @State downloadProgress: number = 0 build() { Column({ space: 30 }) { // 线性进度条 Column() { Text('线性进度条') Progress({ value: 60, total: 100, type: ProgressType.Linear }) .width('100%') .height(8) .color('#1890FF') .backgroundColor('#E0E0E0') } // 圆形进度条 Column() { Text('圆形进度条') Progress({ value: 75, total: 100, type: ProgressType.Circular }) .width(100) .height(100) .color('#4ECDC4') } // 月食进度条 Column() { Text('月食进度条') Progress({ value: 45, total: 100, type: ProgressType.Eclipse }) .width(100) .height(100) .color('#FFD93D') } // 环形进度条 Column() { Text('环形进度条') Progress({ value: this.downloadProgress, total: 100, type: ProgressType.Ring }) .width(120) .height(120) .color('#FF6B6B') .backgroundColor('#E0E0E0') } // 模拟下载 Button('模拟下载') .onClick(() => { if (this.downloadProgress < 100) { this.downloadProgress += 10 } else { this.downloadProgress = 0 } }) } .width('100%') .padding(20) } } ``` ### 4.8.2 加载进度(LoadingProgress) **语法**: ```typescript LoadingProgress() ``` **示例**: ```typescript @Entry @Component struct LoadingProgressExample { @State isLoading: boolean = true build() { Column({ space: 20 }) { if (this.isLoading) { // 基本加载 LoadingProgress() .width(50) .height(50) .color('#1890FF') // 大号加载 LoadingProgress() .width(80) .height(80) .color('#4ECDC4') // 小号加载 LoadingProgress() .width(24) .height(24) .color('#999999') } else { Text('加载完成!') .fontSize(20) } Button(this.isLoading ? '停止加载' : '开始加载') .onClick(() => { this.isLoading = !this.isLoading }) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } } ``` --- ## 4.9 图片组件(Image) ### 4.9.1 基本用法 **语法**: ```typescript Image(src: string | Resource | PixelMap) ``` **示例**: ```typescript @Entry @Component struct ImageExample { build() { Column({ space: 20 }) { // 本地资源图片 Image($r('app.media.icon')) .width(100) .height(100) // 网络图片(需要网络权限) Image('https://via.placeholder.com/300') .width(200) .height(150) .borderRadius(8) // 资源引用 Image($r('app.media.logo')) .width(150) .height(150) } .width('100%') .padding(20) } } ``` ### 4.9.2 图片属性 | 属性 | 类型 | 说明 | 示例 | | ----------------- | ---------------------------- | -------------- | ----------------------------------------- | | `src` | string / Resource / PixelMap | 图片源 | `.src('https://...')` | | `width` | Length | 宽度 | `.width(200)` | | `height` | Length | 高度 | `.height(200)` | | `borderRadius` | Length | 圆角 | `.borderRadius(8)` | | `objectFit` | ImageFit | 填充方式 | `.objectFit(ImageFit.Contain)` | | `objectRepeat` | ImageRepeat | 重复方式 | `.objectRepeat(ImageRepeat.XY)` | | `fitOriginalSize` | boolean | 自适应原始尺寸 | `.fitOriginalSize(true)` | | `autoResize` | boolean | 自动调整大小 | `.autoResize(true)` | | `renderMode` | RenderMode | 渲染模式 | `.renderMode(RenderMode.Template)` | | `interpolation` | ImageInterpolation | 插值方式 | `.interpolation(ImageInterpolation.High)` | | `syncLoad` | boolean | 同步加载 | `.syncLoad(true)` | ### 4.9.3 图片填充模式(ImageFit) | ImageFit | 说明 | 效果 | | ----------- | ---- | -------------------- | | `Contain` | 包含 | 完整显示,等比缩放 | | `Cover` | 覆盖 | 填满容器,可能裁剪 | | `Fill` | 填充 | 完全填满,不保持比例 | | `Auto` | 自动 | 自动选择最佳方式 | | `ScaleDown` | 缩小 | 缩小到容器内 | | `None` | 原始 | 保持原始尺寸 | **示例**: ```typescript @Entry @Component struct ImageFitExample { build() { Column() { Row({ space: 10 }) { Column() { Image($r('app.media.sample')) .width(100) .height(80) .objectFit(ImageFit.Contain) Text('Contain') .fontSize(12) } Column() { Image($r('app.media.sample')) .width(100) .height(80) .objectFit(ImageFit.Cover) Text('Cover') .fontSize(12) } Column() { Image($r('app.media.sample')) .width(100) .height(80) .objectFit(ImageFit.Fill) Text('Fill') .fontSize(12) } } } .width('100%') .padding(20) } } ``` ### 4.9.4 图片加载状态 ```typescript @Entry @Component struct ImageLoadExample { @State imageUrl: string = 'https://via.placeholder.com/300' @State loadSuccess: boolean = false @State loadError: boolean = false build() { Column({ space: 20 }) { Image(this.imageUrl) .width(200) .height(150) .borderRadius(8) .onLoad(() => { console.info('图片加载成功') this.loadSuccess = true this.loadError = false }) .onError(() => { console.error('图片加载失败') this.loadSuccess = false this.loadError = true }) Text(this.loadSuccess ? '加载成功' : this.loadError ? '加载失败' : '未加载') .fontColor(this.loadSuccess ? '#4CAF50' : this.loadError ? '#F44336' : '#999999') Button('重新加载') .onClick(() => { // 改变 URL 触发重新加载 this.imageUrl = 'https://via.placeholder.com/300?t=' + Date.now() }) } .width('100%') .padding(20) } } ``` --- ## 4.10 徽标组件(Badge) ### 4.10.1 基本用法 **语法**: ```typescript Badge(value: { count: number, maxCount?: number, style?: BadgeStyle } | { dot: boolean }, options?: { builder: CustomBuilder, count?: number }) ``` **示例**: ```typescript @Entry @Component struct BadgeExample { @State count: number = 5 build() { Column({ space: 30 }) { // 数字徽标 Badge({ count: this.count, maxCount: 99, style: { badgeSize: 18, badgeColor: '#FF6B6B', fontSize: 12, fontColor: '#FFFFFF' } }) { Image($r('app.media.icon')) .width(60) .height(60) .borderRadius(8) } // 红点徽标 Badge({ dot: true }) { Image($r('app.media.icon')) .width(60) .height(60) .borderRadius(8) } // 自定义徽标内容 Badge({ count: 100, maxCount: 9, style: { badgeSize: 20, badgeColor: '#4ECDC4', fontSize: 10, fontColor: '#FFFFFF' } }) { Column() { Image($r('app.media.icon')) .width(60) .height(60) .borderRadius(8) Text('消息') } } // 增加计数按钮 Button('增加徽标数量') .onClick(() => { this.count++ }) } .width('100%') .padding(20) .justifyContent(FlexAlign.Center) } } ``` --- ## 4.11 符号图标(SymbolGlyph) ### 4.11.1 基本用法 **语法**: ```typescript SymbolGlyph(value: Resource) ``` **示例**: ```typescript @Entry @Component struct SymbolGlyphExample { build() { Column({ space: 20 }) { // 基本符号 SymbolGlyph($r('sys.symbol.ohos_add')) .fontSize(32) .fontColor(['#1890FF']) // 带颜色 SymbolGlyph($r('sys.symbol.ohos_favorite')) .fontSize(40) .fontColor(['#FF6B6B']) // 多色符号 SymbolGlyph($r('sys.symbol.ohos_star')) .fontSize(40) .fontColor(['#FFD93D', '#FF6B6B', '#4ECDC4']) // 常用符号示例 Row({ space: 15 }) { SymbolGlyph($r('sys.symbol.ohos_home')) .fontSize(24) .fontColor(['#333333']) SymbolGlyph($r('sys.symbol.ohos_user')) .fontSize(24) .fontColor(['#333333']) SymbolGlyph($r('sys.symbol.ohos_settings')) .fontSize(24) .fontColor(['#333333']) SymbolGlyph($r('sys.symbol.ohos_trash')) .fontSize(24) .fontColor(['#F44336']) SymbolGlyph($r('sys.symbol.ohos_edit')) .fontSize(24) .fontColor(['#2196F3']) } } .width('100%') .padding(20) .justifyContent(FlexAlign.Center) } } ``` ### 4.11.2 常用系统符号 | 符号 | 名称 | 用途 | | ----------------------------- | ------ | -------- | | `sys.symbol.ohos_add` | 加号 | 添加 | | `sys.symbol.ohos_trash` | 垃圾桶 | 删除 | | `sys.symbol.ohos_edit` | 编辑 | 编辑 | | `sys.symbol.ohos_home` | 主页 | 首页 | | `sys.symbol.ohos_user` | 用户 | 个人中心 | | `sys.symbol.ohos_settings` | 设置 | 设置 | | `sys.symbol.ohos_favorite` | 心形 | 收藏 | | `sys.symbol.ohos_star` | 星星 | 评分 | | `sys.symbol.ohos_search` | 搜索 | 搜索 | | `sys.symbol.ohos_close` | 关闭 | 关闭 | | `sys.symbol.ohos_checkmark` | 对勾 | 确认 | | `sys.symbol.ohos_arrow_right` | 右箭头 | 右导航 | | `sys.symbol.ohos_arrow_left` | 左箭头 | 返回 | | `sys.symbol.ohos_download` | 下载 | 下载 | | `sys.symbol.ohos_upload` | 上传 | 上传 | | `sys.symbol.ohos_share` | 分享 | 分享 | --- ## 4.12 空白填充(Blank) ### 4.12.1 基本用法 **作用**:在容器主轴方向自动填充空白空间 **示例**: ```typescript @Entry @Component struct BlankExample { @State isOn: boolean = true build() { Column() { // 导航栏示例 Row() { Image($r('app.media.back')) .width(24) .height(24) Text('标题') .fontSize(18) .fontWeight(FontWeight.Medium) // 自动填充中间空白 Blank() Image($r('app.media.more')) .width(24) .height(24) } .width('100%') .padding({ left: 16, right: 16 }) .backgroundColor('#FFFFFF') Divider() // 表单示例 Row() { Text('蓝牙') .fontSize(16) Blank() Toggle({ type: ToggleType.Switch, isOn: this.isOn }) .onChange((isOn: boolean) => { this.isOn = isOn }) } .width('100%') .padding({ left: 20, right: 20, top: 15, bottom: 15 }) .backgroundColor('#FFFFFF') } .width('100%') .height('100%') .backgroundColor('#F5F5F5') } } ``` --- ## 4.13 分隔器(Divider) ### 4.13.1 基本用法 **语法**: ```typescript Divider() ``` **示例**: ```typescript @Entry @Component struct DividerExample { build() { Column({ space: 15 }) { // 默认分隔线 Text('上方内容') Divider() Text('下方内容') Divider() // 自定义样式 Row() { Text('左侧') Divider() .vertical(true) .height(40) .color('#E0E0E0') Text('右侧') } Divider() // 彩色分隔线 Column() { Text('分组1') Text('分组1内容') } Divider() .color('#1890FF') .strokeWidth(2) Column() { Text('分组2') Text('分组2内容') } } .width('100%') .padding(20) } } ``` **Divider 属性**: | 属性 | 类型 | 说明 | 示例 | | ------------- | ----------------- | -------- | ------------------------------ | | `vertical` | boolean | 是否垂直 | `.vertical(true)` | | `color` | Color / Resource | 颜色 | `.color('#E0E0E0')` | | `strokeWidth` | number / Resource | 宽度 | `.strokeWidth(1)` | | `lineCap` | LineCapStyle | 端点样式 | `.lineCap(LineCapStyle.Round)` | --- ## 4.14 组件通用属性 ### 4.14.1 尺寸属性 ```typescript // 宽度和高度 .width(100) // 固定值 .width('100%') // 百分比 .width('auto') // 自适应 .height(50) .height('100%') // 最小/最大尺寸 .constraintSize({ minWidth: 50, maxWidth: 200, minHeight: 30, maxHeight: 100 }) ``` ### 4.14.2 布局属性 ```typescript // 外边距 .margin(10) // 四边 .margin({ left: 10, right: 10 }) // 左右 .margin({ top: 10, bottom: 10 }) // 上下 .margin({ left: 10, top: 20, right: 10, bottom: 20 }) // 内边距 .padding(10) .padding({ left: 10, right: 10 }) .padding({ top: 20, bottom: 20 }) // 背景 .backgroundColor('#F5F5F5') .backgroundImage($r('app.media.bg')) .backgroundImageSize(ImageSize.Cover) .backgroundImagePosition({ x: 0, y: 0 }) ``` ### 4.14.3 边框属性 ```typescript // 边框 .border({ width: 1, color: '#E0E0E0', radius: 8, style: BorderStyle.Solid }) // 单独设置 .borderWidth(1) .borderColor('#E0E0E0') .borderRadius(8) // 阴影 .shadow({ radius: 8, color: 'rgba(0, 0, 0, 0.1)', offsetX: 0, offsetY: 2, spread: 0 }) ``` ### 4.14.4 变换属性 ```typescript // 透明度 .opacity(0.5) .opacity(0) // 完全透明 .opacity(1) // 完全不透明 // 旋转 .rotate({ x: 0, y: 0, z: 1, angle: 45 }) // 缩放 .scale({ x: 1.2, y: 1.2 }) // 平移 .translate({ x: 10, y: -5 }) ``` ### 4.14.5 交互属性 ```typescript // 触摸热点区域 .hitTestBehavior(HitTestMode.Default) // 触摸事件 .touchable(true) // 焦点 .focusable(true) .focusOnTouch(true) // 手势优先级 .gesturePriority(GesturePriority.Low) // 触摸逻辑类型 .touchIntercept(( event: TouchEvent, currentDispatch: () => boolean, currentPropagationStop: () => boolean ) => { // 返回 true 阻止事件传递 return false }) ``` ### 4.14.6 可见性 ```typescript // 显示/隐藏 .visibility(Visibility.Visible) // 可见 .visibility(Visibility.Hidden) // 不可见但占位 .visibility(Visibility.None) // 完全隐藏不占位 // 禁用 .enabled(false) // Z 轴层级 .zIndex(1) ``` --- ## 本章小结 1. **ArkUI 声明式特点**:通过 build() 方法返回 UI 描述,状态变化自动触发 UI 更新 2. **基础组件**: - `Text`:文本显示,支持丰富样式和 Span 混排 - `Button`:按钮,支持多种类型和样式 - `TextInput`/`TextArea`:文本输入 - `Checkbox`/`Radio`/`Switch`/`Toggle`:选择组件 - `Slider`:滑块 - `Progress`/`LoadingProgress`:进度显示 - `Image`:图片加载 - `Badge`:徽标 - `SymbolGlyph`:系统符号图标 - `Blank`:空白填充 - `Divider`:分隔线 3. **通用属性**:尺寸、布局、边框、变换、交互、可见性等 ## ForEach 循环渲染 ```ts ForEach( this.arrs , //函数特殊,需要渲染的组件 (item: ItemType) => { Button(item.name).onClick((event: ClickEvent) => { router.push({ url: item.target }) }) }) ``` # Tabs 组件(容器) [选项卡 (Tabs)-构建布局-组件布局-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-tabs) ![img](assets/zh-cn_image_0000002727750128.png) ```ts @Entry @Component struct Index { @State message: string = 'Hello World'; build() { Tabs() { // TabContent选项卡的内容 TabContent() { Text('首页') .fontSize(30) } .tabBar('首页1') // TabContent选项卡的内容 TabContent() { Text('通讯录') .fontSize(30) } .tabBar('通讯录') } } } ``` # 布局组件 [布局概述-组件布局-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-overview) 组件按照布局的要求依次排列,构成应用的页面。在声明式UI中,所有的页面都是由自定义组件构成,开发者可以根据自己的需求,选择合适的布局进行页面开发。 布局指用特定的组件或者属性来管理用户页面所放置UI组件的大小和位置。在实际的开发过程中,需要遵守以下流程保证整体的布局效果: - 确定页面的布局结构。 - 分析页面中的元素构成。 - 选用适合的布局容器组件或属性控制页面中各个元素的位置和大小。 ## Column @Builder布局 装饰器 ![image-20260918150939364](assets/image-20260918150939364.png) ```ts interface TabInfo{ title:string; icon:Resource; } @Entry @Component struct Index { @State message: string = 'Hello World'; // 当前激活的 选项卡 activeIndex:number = 1 tabItems:TabInfo[] = [ {title:'首页',icon:$r('app.media.tab_home')}, {title:'分类',icon:$r('app.media.tab_all_products')}, {title:'购物车',icon:$r('app.media.tab_carts')}, {title:'我的111',icon:$r('app.media.tab_mime')}, ] //用户构建外观的函数 /** * Builder */ @Builder tabBarBiilder(index:number){ Column({space:3}){ //图 Image(this.tabItems[index].icon).width("20") //字 Text(this.tabItems[index].title).fontColor( this.activeIndex==index? Color.Blue : Color.Gray) } } build() { Tabs({ barPosition: BarPosition.End }) { // TabContent选项卡的内容 TabContent() { Text('首页') .fontSize(30) } .tabBar(this.tabBarBiilder( 0 )) // TabContent选项卡的内容 TabContent() { Text('分类') .fontSize(30) } .tabBar(this.tabBarBiilder( 1 )) // TabContent选项卡的内容 TabContent() { Text('购物车') .fontSize(30) } .tabBar(this.tabBarBiilder( 2 )) // TabContent选项卡的内容 TabContent() { Text('我的') .fontSize(30) } .tabBar(this.tabBarBiilder(3 )) } } } ``` ## @State 装饰器 # @State装饰器:组件内状态 更新时间: 2026-09-09 14:54 被状态变量装饰器装饰的变量称为状态变量,使普通变量具备状态属性。当状态变量改变时,会触发其直接绑定的UI组件渲染更新。 在状态变量相关装饰器中,[@State](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-state-management-state#state)是最基础的装饰器,也是大部分状态变量的数据源。 在阅读@State文档前,建议开发者对状态管理框架有基本的了解。建议提前阅读:[状态管理概述](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-management-overview)。最佳实践请参考[状态管理最佳实践](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-status-management)。常见问题请参考[状态管理常见问题](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state-management-faq)。 说明 从API version 9开始,该装饰器支持在ArkTS卡片中使用。 从API version 11开始,该装饰器支持在元服务中使用。 ## 概述 @State装饰的变量与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型并完成本地初始化;若需从父组件初始化,也可选择使用命名参数机制完成赋值。 @State装饰的变量拥有以下特性: - @State装饰的变量生命周期与其所属自定义组件的生命周期相同。 ## 装饰器使用规则说明 | @State变量装饰器 | 说明 | | :------------------- | :----------------------------------------------------------- | | 装饰器参数 | 无 | | 同步类型 | 不与父组件中任何类型的变量同步。 | | 允许装饰的变量类型 | object、class、string、number、boolean、enum类型,以及这些类型的数组。API version 10开始支持[Date类型](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state#装饰date类型变量)。API version 11及以上支持[Map](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state#装饰map类型变量)、[Set](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state#装饰set类型变量)类型、undefined和null类型、ArkUI框架定义的联合类型[Length](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-types#length)、[ResourceStr](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-types#resourcestr)、[ResourceColor](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-types#resourcecolor)类型以及这些类型的联合类型,示例见[@State支持联合类型实例](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state#state支持联合类型实例)。支持类型的场景见[观察变化](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-state#观察变化)。 | | 不允许装饰的变量类型 | 不允许装饰Function类型。 | | 被装饰变量的初始值 | 必须本地初始化。 | ## 变量的传递/访问规则说明 | 传递/访问 | 说明 | | :----------------- | :----------------------------------------------------------- | | 从父组件初始化 | 可以从父组件或本地初始化。父组件传入非undefined值时覆盖本地初始值,否则使用@State的本地初始值。支持父组件中的常规变量以及装饰器装饰的状态变量:@State、[@Link](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-link)、[@Prop](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-prop)、[@Provide](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-provide-and-consume)、[@Consume](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-provide-and-consume)、[@ObjectLink](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-observed-and-objectlink)、[@StorageLink](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-appstorage#storagelink)、[@StorageProp](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-appstorage#storageprop)、[@LocalStorageLink](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-localstorage#localstoragelink)和[@LocalStorageProp](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-localstorage#localstorageprop),初始化@State。需要注意:父组件传入的外部变量对@State初始化时,仅作为初始值,后续变量的变化不会同步至@State。 | | 用于初始化子组件 | @State装饰的变量支持初始化子组件的常规变量、@State、@Link、@Prop、@Provide。 | | 是否支持组件外访问 | 不支持,只能在组件内访问。 | ```ts interface TabInfo{ title:string; icon:Resource; } @Entry @Component struct Index { @State message: string = 'Hello World'; // 当前激活的 选项卡 // 告诉使用当前变量的 界面,当变量有更新的 重新的绘制页面 @State activeIndex:number = 3 tabItems:TabInfo[] = [ {title:'首页',icon:$r('app.media.tab_home')}, {title:'分类',icon:$r('app.media.tab_all_products')}, {title:'购物车',icon:$r('app.media.tab_carts')}, {title:'我的',icon:$r('app.media.tab_mime')}, ] //用户构建外观的函数 /** * Builder */ @Builder tabBarBiilder(index:number){ Column({space:3}){ //图 Image(this.tabItems[index].icon).width("20") //字 Text(this.tabItems[index].title+"-"+this.activeIndex).fontColor( this.activeIndex==index? Color.Blue : Color.Gray) } } build() { Tabs({ barPosition: BarPosition.End }) { // TabContent选项卡的内容 TabContent() { Text('首页') .fontSize(30) } .tabBar(this.tabBarBiilder( 0 )) // TabContent选项卡的内容 TabContent() { Text('分类') .fontSize(30) } .tabBar(this.tabBarBiilder( 1 )) // TabContent选项卡的内容 TabContent() { Text('购物车') .fontSize(30) } .tabBar(this.tabBarBiilder( 2 )) // TabContent选项卡的内容 TabContent() { Text('我的') .fontSize(30) } .tabBar(this.tabBarBiilder(3 )) } .onChange((index:number)=>{ this.activeIndex = index console.log("切换选项: "+index,this.activeIndex) }) } } ``` Scrollz组件 可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。支持设置滚动方向、滚动条、边缘效果、嵌套滚动以及自由滚动缩放等能力,适用于内容超出显示区域或需要复杂滚动交互的场景。 说明 - 该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 - 该组件嵌套List子组件滚动时,若List不设置宽高,则默认全部加载。在对性能有要求的场景下,开发者应指定List的宽高,以避免默认全部加载影响性能。最佳实践请参考[懒加载优化性能——Scroll嵌套List导致按需加载失效](https://developer.huawei.com/consumer/cn/doc/best-practices/bpta-lazyforeach-optimization#section6296154115367)。 - 该组件滚动的前提是主轴方向大小小于内容大小。 - Scroll组件通用属性[clip](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-sharp-clipping#clip12)的默认值为true。 - Scroll组件的高度超出屏幕显示范围时,可以通过设置通用属性[layoutWeight](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-size#layoutweight)让Scroll高度适应主轴的剩余空间。 - 手指触摸屏幕时,会停止当前触摸范围内所有滚动组件的滚动动画([scrollTo](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-scroll#scrollto)和[scrollToIndex](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-scroll#scrolltoindex)接口触发的滚动动画除外),包括边缘回弹动画。 - 组件内部已绑定手势实现跟手滚动等功能,需要增加自定义手势操作时请参考[手势拦截增强](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-gesture-blocking-enhancement)进行处理。 ## List组件 [创建列表 (List)-列表与网格-UI开发 (ArkTS声明式开发范式)-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-create-list) ## 概述 列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求(如通讯录、音乐列表、购物清单等)。 使用列表可以轻松高效地显示结构化、可滚动的信息。通过在[List](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-list)组件中按垂直或者水平方向线性排列子组件[ListItemGroup](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-listitemgroup)或[ListItem](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-listitem),为列表中的行或列提供单个视图,或使用[循环渲染](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-foreach)迭代一组行或列,或混合任意数量的单个视图和ForEach结构,构建一个列表。List组件支持使用[条件渲染](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-ifelse)、循环渲染、[懒加载](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-lazyforeach)等[渲染控制](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-rendering-control-overview)方式生成子组件。 在圆形屏幕设备上,推荐使用[ArcList](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-arclist)组件,使用方式可参考[创建弧形列表 (ArcList)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-layout-development-create-arclist)。 以下各步骤示例为片段代码,可通过点击示例代码右下方的链接获取完整示例。 ## 布局与约束 列表作为一种容器,会自动按其滚动方向排列子组件,向列表中添加组件或从列表中移除组件会重新排列子组件。 如下图所示,在垂直列表中,List按垂直方向自动排列ListItemGroup或ListItem。 ListItemGroup用于列表数据的分组展示,其子组件也是ListItem。ListItem表示单个列表项,可以包含单个子组件。 ![image-20260918160200880](assets/image-20260918160200880.png) ![image-20260918160217572](assets/image-20260918160217572.png)