鸿蒙新特性——QRCode 二维码组件详解
一、引言
二维码已经渗透到日常生活的每个角落。扫码支付、扫码加好友、扫码连接 WiFi、扫码打开网页——二维码从技术上讲是一种信息编码方式,但从产品体验上讲,它是一种"物理世界到数字世界的快捷入口"。几乎每个 App 都有生成二维码的能力:分享链接时生成二维码让朋友扫码打开、设备配网时生成二维码让用户扫描连接、个人名片页生成二维码方便交换联系方式。
二维码的生成原理并不复杂——将字符串按 QR Code 标准编码为黑白像素矩阵。但"不复杂"不代表"容易实现"。如果在应用中自己编写 QR Code 编码算法,需要考虑纠错等级选择、版本自适应、掩码模式、数据编码模式等底层细节——这些在任何编程语言中都是一项不小的工程。
HarmonyOS 提供了 QRCode 组件——一个内置于 ArkUI 的二维码生成组件。开发者只需要传入一个字符串,QRCode 自动完成编码、纠错、版本选择、矩阵渲染的全部过程。生成的二维码图案以组件形式直接渲染到 UI 中,响应式更新——输入内容变化时二维码自动重新生成,无需手动触发。
本文通过一个二维码生成器 Demo 深入讲解 QRCode 组件的核心用法:如何生成不同类型内容的二维码?如何自定义前景色和背景色?如何调整二维码尺寸?如何实现实时生成?
阅读完本文,你将能够:
- 使用 QRCode 组件生成 URL、纯文本、电话、邮箱、WiFi 配置等二维码
- 使用
color()和backgroundColor()自定义二维码的外观配色 - 结合 TextInput 的
onChange实现输入内容实时生成二维码 - 调整二维码尺寸以适应不同的展示场景
二、QRCode 组件 API 总览
2.1 构造函数
QRCode(value: ResourceStr)
QRCode 的构造函数极其简洁——接收一个字符串参数,自动将其编码为二维码。字符串可以是任何内容:网址、纯文本、电话号码、WiFi 配置等。
// 生成网址二维码
QRCode('https://www.harmonyos.com')
// 生成纯文本二维码
QRCode('你好,鸿蒙!')
// 生成电话号码二维码
QRCode('tel:13800138000')
构造函数没有额外的配置项——所有定制都通过链式方法完成。
2.2 核心方法
QRCode 的方法极其精简,只有两个样式方法:
| 方法 | 用途 | 默认值 | 示例 |
|---|---|---|---|
color(value: ResourceColor) |
二维码图案颜色(前景色) | '#000000' |
.color('#1677FF') |
backgroundColor(value: ResourceColor) |
二维码背景颜色 | '#FFFFFF' |
.backgroundColor('#F2F3F5') |
注意:QRCode 继承自 CommonMethod,因此也拥有通用的尺寸方法(width/height)、背景方法等。
2.3 基本用法模式
@State qrContent: string = 'https://www.harmonyos.com';
@State qrColor: string = '#1a1a2e';
@State qrBgColor: string = '#FFFFFF';
QRCode(this.qrContent)
.color(this.qrColor)
.backgroundColor(this.qrBgColor)
.width(200)
.height(200)
最简用法只需要一行构造函数——QRCode 自动处理编码和渲染:
QRCode('https://www.harmonyos.com')
2.4 响应式更新
QRCode 是声明式组件,当构造函数的参数(字符串)或链式方法的参数(颜色、尺寸)发生变化时,二维码自动重新生成。这意味着你不需要手动调用任何"刷新"方法——绑定 @State 变量即为实时更新:
@State content: string = '';
TextInput({ placeholder: '输入内容', text: this.content })
.onChange((value: string) => { this.content = value; })
QRCode(this.content) // content 变化时自动重新生成二维码
.width(200).height(200)
2.5 二维码内容格式
QRCode 接受的字符串内容可以按特定格式编码,以适配不同的终端识别行为:
| 内容类型 | 编码格式 | 扫码行为 |
|---|---|---|
| 网址链接 | https://example.com |
直接打开网页 |
| 纯文本 | 你好鸿蒙 |
显示文本内容 |
| 电话号码 | tel:13800138000 |
弹出拨号界面 |
| 邮箱地址 | mailto:hello@example.com |
打开发送邮件界面 |
| WiFi 配置 | WIFI:S:SSID;T:WPA;P:password;; |
自动连接 WiFi |
| 短信 | SMSTO:13800138000:你好 |
打开短信编辑界面 |
| 地理坐标 | geo:39.9087,116.3975 |
打开地图定位 |
其中 WiFi 配置的格式最为固定:WIFI:S:<网络名>;T:<加密方式>;P:<密码>;;
S:后是 WiFi 的 SSID(网络名称)T:后是加密类型:WPA(最常见)、WEP、nopass(无密码)P:后是密码(如果T:nopass则省略此字段)- 末尾的
;;是格式要求的结束标记
不同扫码 App 对这些格式的支持程度不同,但 URL、文本、电话和邮件是通用标准。
三、Demo 设计:二维码生成器
3.1 功能概述
Demo 是一个二维码生成器页面,模拟实际 App 中的"分享二维码"或"扫码加好友"功能:
- 5 种内容类型预设:网址、文本、电话、邮箱、WiFi——用户点击预设按钮快速切换
- 实时生成:二维码随输入内容变化实时更新
- 前景色选择器:8 种预设颜色(黑、蓝、绿、红、粉、橙、紫、青)供用户选择
- 背景色选择器:7 种背景色(白、灰、暖黄、浅绿、浅蓝、浅粉、黑)供用户选择
- 尺寸调节:三种预设尺寸(150×150、200×200、250×250)
- 实时预览:二维码放大显示在页面中央,当前内容类型在下方标注
3.2 内容类型预设
interface TypePreset {
label: string;
type: string;
value: string;
}
private typePresets: TypePreset[] = [
{ label: '网址', type: 'URL', value: 'https://www.harmonyos.com' },
{ label: '文本', type: 'Text', value: '你好,鸿蒙!Hello HarmonyOS' },
{ label: '电话', type: 'Phone', value: 'tel:13800138000' },
{ label: '邮箱', type: 'Email', value: 'mailto:hello@harmonyos.com' },
{ label: 'WiFi', type: 'WiFi', value: 'WIFI:S:HarmonyOS_5G;T:WPA;P:12345678;;' }
];
每个预设包含:展示名称(label)、类型标识(type)和实际的编码字符串(value)。用户点击预设按钮时,二维码内容和标签同步更新:
.onClick(() => {
this.contentType = preset.type;
this.contentLabel = preset.label;
this.qrContent = preset.value;
})
预设按钮使用"选中/未选中"的双色样式:选中状态蓝色背景白字,未选中状态灰色背景黑字——与分段控制器的视觉模式一致。
3.3 QRCode 核心渲染
QRCode(this.qrContent)
.color(this.qrColor)
.backgroundColor(this.qrBgColor)
.width(this.qrSize)
.height(this.qrSize)
四个参数全部绑定到 @State 变量:
this.qrContent:从 TextInput 或预设按钮获取的内容字符串this.qrColor:从前景色选择器获取的颜色值this.qrBgColor:从背景色选择器获取的颜色值this.qrSize:从尺寸按钮获取的尺寸值(150/200/250)
当任意状态变化时,二维码自动重新生成——这就是声明式 UI 的优势:变量改变即 UI 刷新,不需要手动调用"重新生成"函数。
3.4 颜色选择器
前景色和背景色选择器采用彩色圆点阵列(Flex 自动换行布局),当前选中的颜色显示蓝色外圈:
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.presetColors, (color: string) => {
Column()
.width(32)
.height(32)
.borderRadius(16)
.backgroundColor(color)
.border({
width: this.qrColor === color ? 3 : 1,
color: this.qrColor === color ? '#1677FF' : '#E8E8ED'
})
.onClick(() => { this.qrColor = color; })
})
}
.width('100%')
使用 Flex({ wrap: FlexWrap.Wrap }) 而非 Row 是因为颜色较多(8 个前背景色 + 7 个背景色),屏幕宽度可能放不下——Flex 自动换行确保所有色块可见。
3.5 尺寸调节
尺寸使用三个预设按钮(小/中/大),点击后直接设置 qrSize:
Button('小').onClick(() => { this.qrSize = 150; })
Button('中').onClick(() => { this.qrSize = 200; })
Button('大').onClick(() => { this.qrSize = 250; })
150vp 适合卡片内嵌场景,200vp 适合详情页展示,250vp 适合全屏展示——三种尺寸覆盖了常见的业务需求。
3.6 页面结构
┌──────────────────────────────────────────┐
│ 📷 二维码生成器(深色标题栏) │
├──────────────────────────────────────────┤
│ 📘 QRCode 组件说明卡片 │
├──────────────────────────────────────────┤
│ ┌ 二维码预览 ──────────────────────┐ │
│ │ │ │
│ │ ████████████████████████ │ │
│ │ ████ ██████ ██ ████ │ │
│ │ ████ ██████ ██ ████ │ │
│ │ ████████████████████████ │ │
│ │ ... │ │
│ │ │ │
│ │ 200 × 200 │ │
│ │ 当前内容:网址链接 │ │
│ └───────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ ┌ 内容类型 ────────────────────────┐ │
│ │ [网址] [文本] [电话] [邮箱] [WiFi]│ │
│ └───────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ ┌ 自定义内容 ──────────────────────┐ │
│ │ [请输入文本或链接... ] │ │
│ └───────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ ┌ 前景色 ──────────────────────────┐ │
│ │ ⬤ ⬤ ⬤ ⬤ ⬤ ⬤ ⬤ ⬤ │ │
│ └───────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ ┌ 背景色 ──────────────────────────┐ │
│ │ ○ ○ ○ ○ ○ ○ ○ │ │
│ └───────────────────────────────────┘ │
├──────────────────────────────────────────┤
│ ┌ 尺寸调节 ────────────────────────┐ │
│ │ 200×200 [小] [中] [大] │ │
│ └───────────────────────────────────┘ │
└──────────────────────────────────────────┘

四、QRCode 组件的最佳实践
4.1 颜色对比度
二维码识别的核心是前景色与背景色之间有足够的对比度。扫描器通过检测明暗模块的排列来解码,如果前景色和背景色对比度不足(例如浅灰前景 + 白色背景),扫描器可能无法正确识别。
推荐组合:
- 深色前景 + 浅色背景(如
#1a1a2e+#FFFFFF)——最高对比度,100% 可扫描 - 品牌色前景 + 白色背景(如
#1677FF+#FFFFFF)——兼顾品牌和可读性 - 白色前景 + 深色背景(如
#FFFFFF+#1a1a2e)——深色模式下的反转配色
避免的组合:
- 浅色前景 + 浅色背景(如黄色 + 白色)
- 相近色前景和背景(如深蓝 + 深紫)
- 红色前景 + 绿色背景(色盲用户完全无法分辨)
4.2 尺寸与扫描距离
二维码的显示尺寸直接影响扫描距离和成功率:
| 屏幕尺寸 | 推荐扫描距离 | 适用场景 |
|---|---|---|
| 100vp | < 15cm | 卡片内嵌的小型二维码 |
| 150vp | 15~30cm | 列表项中的二维码 |
| 200vp | 30~50cm | 详情页展示 |
| 250vp+ | 50~100cm | 大屏设备、平板 |
一般来说,二维码尺寸不应小于 100vp——再小的话,摄像头在正常距离下无法对焦到足够的模块细节。
4.3 实时生成的性能
QRCode 组件在每次参数变化时重新编码和渲染。当用户在 TextInput 中输入时,onChange 每次触发都会更新 @State,导致二维码重新生成。对于几十个字符的短内容,这是完全流畅的。
但如果绑定到很长的文本(>1000 字符),每次输入都重新生成可能有可见延迟。优化策略:
- 在
onChange中使用防抖(300~500ms 延迟后才更新 @State) - 对于长文本,提供一个"生成"按钮手动触发,而非实时生成
- 使用
cachedCount(如果 QRCode 在 Swiper 等容器中)预缓存渲染结果
不过对于典型的二维码使用场景(网址、联系方式等短文本),实时生成完全不需要优化。
4.4 QRCode 与 Image 的选择
QRCode 组件生成的是原生矢量矩阵图案,Image 组件加载的是预先准备好的 PNG/JPG 图片。两者的选择:
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 用户内容动态生成 | QRCode | 无需预生成图片,响应式更新 |
| 固定不变的公司二维码 | Image | 一次生成后反复使用,节省编码开销 |
| 需要在弹窗/浮层中展示 | QRCode | 声明式渲染,与弹窗生命周期绑定 |
| 需要分享到其他 App | 截屏或导出 | QRCode 本身不能直接导出为图片文件 |
QRCode 组件生成的是屏幕渲染结果,不是图片文件。如果需要保存二维码为图片文件(用于分享到微信等),需要额外使用截图 API 或 Canvas 导出。
4.5 纠错等级
QR Code 标准有四个纠错等级:L(7%)、M(15%)、Q(25%)、H(30%)。百分比表示"即使这么多面积被遮挡,仍可正确扫描"。
QRCode 组件不暴露纠错等级配置(自动选择最优等级),但在设计二维码展示时需要注意:
- 高纠错等级会生成更密集的图案(更多模块),需要更大的尺寸才能清晰扫描
- 如果计划在二维码中央叠加 Logo(如品牌标志),系统会自动使用更高的纠错等级以补偿 Logo 遮挡
4.6 安全性考虑
二维码是一种"所见非所得"的信息载体——用户看到的是一堆黑白方块,但扫码后的行为(打开网页、拨打电话、发送邮件)可能出乎意料。作为开发者:
- 预览真实内容:在二维码下方显示实际会被解码的内容(如本文 Demo 的"当前内容"标签),让用户在扫码前就能判断二维码的可信度
- 不编码敏感信息:不要在二维码中编码密码、Token、身份证号等敏感信息——二维码的内容是明文存储的,任何扫描器都能读取
- WiFi 密码注意:WiFi 类型的二维码包含了明文密码,应仅在受控环境中使用(如家庭路由器配置),不要在公开场合展示
五、完整代码结构
QRCodePage (~275 行)
├── 接口
│ └── TypePreset — 内容类型预设接口
├── 状态变量
│ ├── @State qrContent — 二维码内容字符串
│ ├── @State qrColor — 前景色
│ ├── @State qrBgColor — 背景色
│ ├── @State qrSize — 二维码尺寸
│ ├── @State contentType — 当前内容类型标识
│ └── @State contentLabel — 当前内容类型标签
├── 数据
│ ├── presetColors: string[] — 8 种前景色预设
│ ├── presetBgColors: string[] — 7 种背景色预设
│ └── typePresets: TypePreset[] — 5 种内容类型预设
├── 视图
│ ├── 标题栏 — 📷 二维码生成器
│ ├── 说明卡片 — QRCode 组件介绍
│ ├── 二维码预览区
│ ├── 内容类型预设按钮
│ ├── 自定义内容 TextInput
│ ├── 前景色选择器
│ ├── 背景色选择器
│ └── 尺寸调节按钮
└── (无 @Builder——所有布局内联)
六、总结
本文通过一个二维码生成器 Demo 深入讲解了 HarmonyOS 中的 QRCode 二维码组件。QRCode 将复杂的 QR Code 编码算法封装为一个简单的声明式组件——开发者只需要传入字符串即可生成二维码图案,内容的编码、纠错、版本适配、渲染全部由 QRCode 内部完成。
核心要点回顾:
-
QRCode 是"字符串 → 像素矩阵"的转换器:构造函数接收字符串,内部完成 QR Code 标准的全部编码流程,输出可扫描的二维码图案。开发者不需要理解 QR Code 的编码算法。
-
color 和 backgroundColor 是唯二的外观控制方法:前景色控制二维码模块的颜色,背景色控制底层背景。两者之间需要足够的对比度以保证可扫描性。
-
声明式更新是 QRCode 的核心使用模式:绑定 @State 变量到构造函数和样式方法,变量变化时二维码自动重新生成。结合 TextInput 的
onChange即可实现输入内容实时生成二维码。 -
不同内容格式决定扫码行为:URL(打开网页)、tel(拨号)、mailto(发邮件)、WiFi(连接网络)——QRCode 只负责生成图案,格式的正确性由开发者保证。
-
二维码尺寸应在 100~250vp 之间:太小难以扫描,太大浪费空间。200vp 是大多数场景的最佳选择。
-
安全性不容忽视:二维码内容对扫描者完全透明。在二维码下方标注内容摘要、避免在二维码中编码敏感信息——是开发者的基本责任。
QRCode 是 ArkUI 中最"即插即用"的组件之一——API 只有三个方法(构造函数 + color + backgroundColor),但实际价值远超其复杂度。任何一个需要"分享"或"传输"功能的 App 都离不开二维码,而 QRCode 让这个看似复杂的任务变得简单自然。
七、扩展思考
QRCode 组件覆盖了基础的二维码生成需求,但在实际项目中,二维码的展示和使用还有更多维度:
在二维码中央叠加 Logo:很多品牌的二维码会在中央放置一个小型品牌 Logo。QRCode 组件本身不支持叠加图片,但可以通过 Stack 布局将 QRCode 和 Image 叠加在一起——Logo 的尺寸应不超过二维码面积的 15%,以保留足够的纠错冗余。
导出二维码为图片:QRCode 是屏幕上的渲染结果,不是图片文件。如果需要将二维码保存为文件(用于分享到微信、保存到相册),需要结合 Canvas 的截图能力或使用第三方库手动编码。
二维码与 RFID/NFC 的协同:在物联网场景中,二维码和 NFC 标签可以互为补充——近距离用 NFC 触碰配对,远距离用二维码扫描配对。两者的编码内容应保持一致。
二维码美化:QRCode 组件只提供纯色设置。如果需要渐变、圆角模块等高级美化效果,需要超出 QRCode 的能力范围——这类定制通常需要使用 Canvas 从头绘制。
动态二维码:某些场景(如双因素认证)需要在页面刷新时生成新的二维码。结合 setInterval 定时更新 @State 变量,QRCode 会自动重新生成——这是动态二维码的简单实现方式。
理解 QRCode 的定位——字符串到二维码图案的声明式转换组件——是正确使用它的关键。它不是一个集成化的"分享二维码"业务组件(不含弹出菜单、保存按钮、社交分享等),而是专注于一个核心任务:将字符串编码为二维码并在屏幕上渲染。这种单一职责使得 QRCode 可以无缝嵌入到任何需要二维码的场景中——从支付码到分享码、从设备配网到名片交换。
通过本文的 Demo——二维码生成器页面,你将 QRCode 组件与 TextInput、颜色选择器和尺寸控制组合在一起,构建了一个完整的二维码实时生成工具。这个页面展示了 QRCode 作为"即插即用"组件的核心价值——用最少的 API 完成最常见的任务。
更多推荐




所有评论(0)