鸿蒙新特性:QRCode 组件 — 二维码生成与多场景应用深度解析
摘要:ArkUI的QRCode组件简化了二维码生成,只需一行代码即可将字符串转换为可扫描的二维码。文章通过构建一个多类型二维码生成器(支持URL、文本、WiFi、名片四种场景),解析了二维码的核心技术: 实现方案对比:原生Canvas绘制复杂且需遵循QR标准(1500+行代码),而QRCode组件由系统底层封装,仅需传入字符串即可自动完成编码与渲染。 关键特性:支持自定义尺寸(120-400vp)
二维码已经成为连接物理世界和数字世界的标准方式——扫码支付、WiFi分享、名片交换、URL跳转,几乎所有"手机扫一扫"的场景背后都是二维码。ArkUI 的
QRCode组件把二维码生成变成了真正的"一行代码":传入字符串,输出可扫的二维码。本文用它构建一个多类型二维码生成器,覆盖 URL、文本、WiFi、名片四种场景,并深入解析二维码在移动应用中的最佳实践。
一、为什么需要 QRCode 组件?
在没有 QRCode 组件之前,在应用中生成二维码有两条路:
方案一:Canvas 自绘(工作量巨大)
- 引入或手写 QR 编码算法(Reed-Solomon 纠错码、掩码模式选择、数据编码)
- 用 Canvas API 逐像素绘制 21×21 到 177×177 的矩阵
- 处理不同纠错级别(L/M/Q/H)对应的模块数量差异
- 预留静区(quiet zone)边距
- 确保打印/缩放后仍可扫描
这是一项需要深入理解 QR Code ISO 18004 标准的工作——随便一个实现(如 qrcodejs)源代码超过 1500 行。
方案二:第三方 JS/C++ 库
引入第三方 QR 编码库,通过 Native Binding 调用。会带来额外的包体积、兼容性风险和接口维护成本。
QRCode 组件由系统底层实现二维码编码,开发者只需要传入字符串——框架自动完成数据编码、纠错码生成、模块布局和渲染。
QRCode('https://www.harmonyos.com')
.width(200)
.height(200)
两行代码,一个可被任意扫码工具识别的标准二维码就完成了。
二、QRCode 核心 API
2.1 基本语法
QRCode(value: string)
.width(length)
.height(length)
.backgroundColor(Color)
value:要编码的字符串内容。这是唯一必填的构造参数,QRCode 会将该字符串编码为二维码。.width()/.height():二维码的显示尺寸。推荐设为相等值(正方形),范围建议 120~400vp。太小可能导致扫描困难,太大则超出屏幕。.backgroundColor():二维码的背景色。默认为透明或白色系,可设为任意颜色。注意浅色背景 + 深色模块对比度更高,更易扫描。
2.2 内容长度与纠错
二维码有四个纠错级别,由系统根据内容长度自动选择:
| 纠错级别 | 可恢复比例 | 适用场景 |
|---|---|---|
| L(低) | ~7% | 屏幕显示,无物理损伤风险 |
| M(中) | ~15% | 一般打印用途 |
| Q(中高) | ~25% | 可能被部分遮挡 |
| H(高) | ~30% | 可能被大面积遮挡或损坏 |
屏幕上的二维码(如本文 Demo)使用 L 级别即可——没有物理折损风险。对于要在户外/包装上打印的二维码,系统会自动使用更高级别。
不同版本(模块数)对应不同容量:
- 版本 1(21×21):最多 25 个字母数字
- 版本 10(57×57):最多 395 个字母数字
- 版本 40(177×177):最多 4296 个字母数字
对于 URL(~50字符)、WiFi 配置(~100字符)、名片 vCard(~200字符),二维码完全够用。
2.3 三种内容类型的编码标准
不同场景有不同的标准格式——直接传任意字符串虽然能生成二维码,但扫码端可能无法正确解析。
URL 链接
https://www.harmonyos.com
最简单的格式,直接传入完整 URL。扫码后浏览器/应用会自动打开该链接。
WiFi 网络配置
WIFI:T:WPA2;S:MyWiFi;P:12345678;;
扫码后手机会自动连接该 WiFi,无需手动输入密码。字段说明:
T:加密方式(WPA2/WPA/WEP/nopass)S:网络名称(SSID)P:密码H:隐藏网络(true/false,可选)
名片 vCard
BEGIN:VCARD
VERSION:3.0
N:张三
TEL:13800138000
EMAIL:zhangsan@example.com
ORG:华为技术有限公司
END:VCARD
扫码后手机自动弹出"添加联系人"界面,姓名/电话/邮箱/公司已预填。这是商务场景中最常用的二维码格式。
2.4 二维码的视觉安全
二维码模块的标准颜色是黑色。但出于品牌表达或美观需要,可以自定义颜色。要注意:
- 深色模块 + 浅色背景:可扫描性最好
- 彩色模块:只要与背景有足够对比度即可
- 反色(白模块+黑背景):多数扫码器支持
- 避免:浅色模块 + 浅色背景、渐变填充、低对比度
2.5 最小尺寸建议
二维码的物理尺寸直接影响扫描距离和成功率:
| 屏幕场景 | 推荐尺寸 | 扫描距离 |
|---|---|---|
| App 内的电子二维码 | 160×160 ~ 200×200 vp | 10~30cm |
| 收银台/闸机屏幕 | 240×240 ~ 320×320 vp | 20~50cm |
| 大屏/电视 | 300×300 ~ 400×400 vp | 1~3m |
太小(<120vp)会导致手机摄像头无法聚焦,尤其在中低端设备上扫描成功率急剧下降。

三、Demo:多类型二维码生成器
本 Demo 构建一个可切换内容类型的二维码生成器——支持 URL 链接、文本、WiFi 配置、名片四种场景,每种场景有不同的输入字段,输入即生成。
页面结构
QRCodeDemoPage (~270行)
├── Header(📱 QR码生成器 + 内容字符数)
├── 类型选择栏(链接/文本/WiFi/名片,4个Tab按钮)
├── Scroll
│ ├── 输入区域(白卡片)
│ │ ├── 链接模式:TextInput(单行URL输入)
│ │ ├── 文本模式:TextArea(多行自由文本)
│ │ ├── WiFi模式:SSID + 密码 + 加密方式选择
│ │ └── 名片模式:姓名 + 电话 + 邮箱 + 公司
│ └── 预览区域(白卡片)
│ ├── 尺寸控制(- / Nx / +)
│ ├── QRCode 组件
│ └── 当前内容描述
类型切换设计
四个类型使用不同颜色区分,选中态为填充色按钮,非选中态为灰色轮廓:
enum QRType {
URL = '链接',
TEXT = '文本',
WIFI = 'WiFi',
CONTACT = '名片'
}
getTypeColor(type: QRType): string {
switch (type) {
case QRType.URL: return '#1677FF'; // 蓝
case QRType.TEXT: return '#52C41A'; // 绿
case QRType.WIFI: return '#722ED1'; // 紫
case QRType.CONTACT: return '#E67E22'; // 橙
}
}
切换类型时,自动根据当前输入更新二维码内容(selectedType 变化 → updateQRContent() → 重新生成对应的标准格式字符串)。
四种输入界面
链接模式
最简单的模式——单行 TextInput,预填 https://www.harmonyos.com。用户输入时实时更新二维码。
if (this.selectedType === QRType.URL) {
TextInput({ text: this.urlInput, placeholder: '请输入URL链接地址' })
.width('100%').height(44)
.onChange((value: string) => {
this.urlInput = value;
this.updateQRContent();
})
}
文本模式
多行 TextArea,支持任意文本。适合生成长段文字二维码(如便签、说明、诗歌)。预填"你好,鸿蒙!Hello HarmonyOS!"。
if (this.selectedType === QRType.TEXT) {
TextArea({ text: this.textInput, placeholder: '请输入任意文本内容' })
.width('100%').height(100)
.onChange((value: string) => {
this.textInput = value;
this.updateQRContent();
})
}
WiFi 模式
三个配置项:网络名称(SSID)、密码、加密方式。使用 WIFI 标准格式拼接:
this.qrContent = `WIFI:T:${this.wifiEncryption};S:${this.wifiSsid};P:${this.wifiPassword};;`;
加密方式提供四个选项:WPA2(默认)、WPA、WEP、无(开放网络)。这在咖啡馆、酒店等场景非常有用——扫码即可连 WiFi,不需要手动输入密码。
名片模式
四个字段:姓名、电话、邮箱、公司。使用 vCard 3.0 格式编码:
this.qrContent =
`BEGIN:VCARD\nVERSION:3.0\nN:${this.contactName}\nTEL:${this.contactPhone}\n` +
`EMAIL:${this.contactEmail}\nORG:${this.contactCompany}\nEND:VCARD`;
扫码后手机通讯录自动识别并弹出添加联系人界面。商务会议中这个场景极其常见——不需要交换纸质名片,扫一扫即可。
尺寸控制
两个圆形按钮(- / +)让用户调整二维码尺寸,范围 120~320vp,每次步进 40vp:
.onClick(() => {
if (this.qrSize > 120) {
this.qrSize -= 40;
}
})
实时显示当前缩放倍率(如 “5x”、“6x”),给用户直观的尺寸反馈。
三个交互点
- 类型切换 — 点击四个类型 Tab,输入区自动切换对应表单,QRCode 实时更新
- 输入即生成 — 任何字段内容变化时,二维码自动重新编码
- 尺寸缩放 — 点击 +/- 按钮调整二维码显示大小(120~320vp)

四、完整代码
import { AppColors, BorderRadius, FontSize, Spacing } from '../common/Constants';
import { promptAction } from '@kit.ArkUI';
enum QRType {
URL = '链接',
TEXT = '文本',
WIFI = 'WiFi',
CONTACT = '名片'
}
interface QRField {
label: string;
placeholder: string;
value: string;
}
@Entry
@Component
struct QRCodeDemoPage {
@State selectedType: QRType = QRType.URL;
@State qrContent: string = 'https://www.harmonyos.com';
@State qrSize: number = 200;
@State urlInput: string = 'https://www.harmonyos.com';
@State textInput: string = '你好,鸿蒙!Hello HarmonyOS!';
@State wifiSsid: string = 'MyWiFi';
@State wifiPassword: string = '12345678';
@State wifiEncryption: string = 'WPA2';
@State contactName: string = '张三';
@State contactPhone: string = '13800138000';
@State contactEmail: string = 'zhangsan@example.com';
@State contactCompany: string = '华为技术有限公司';
aboutToAppear(): void {
this.updateQRContent();
}
updateQRContent(): void {
switch (this.selectedType) {
case QRType.URL:
this.qrContent = this.urlInput.trim() || 'https://www.harmonyos.com';
break;
case QRType.TEXT:
this.qrContent = this.textInput.trim() || 'Hello HarmonyOS';
break;
case QRType.WIFI:
this.qrContent =
`WIFI:T:${this.wifiEncryption};S:${this.wifiSsid};P:${this.wifiPassword};;`;
break;
case QRType.CONTACT:
this.qrContent =
`BEGIN:VCARD\nVERSION:3.0\nN:${this.contactName}\nTEL:${this.contactPhone}\nEMAIL:${this.contactEmail}\nORG:${this.contactCompany}\nEND:VCARD`;
break;
}
}
getTypeColor(type: QRType): string {
switch (type) {
case QRType.URL: return '#1677FF';
case QRType.TEXT: return '#52C41A';
case QRType.WIFI: return '#722ED1';
case QRType.CONTACT: return '#E67E22';
}
}
build() {
Column() {
Row() {
Text('📱 QR码生成器')
.fontSize(FontSize.HEADLINE)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
.layoutWeight(1)
Text(`${this.qrContent.length}字符`)
.fontSize(10)
.fontColor('#FFFFFF88')
}
.width('100%')
.height(52)
.backgroundColor('#1a1a2e')
.padding({ left: Spacing.XXL, right: Spacing.XXL })
Row() {
ForEach([QRType.URL, QRType.TEXT, QRType.WIFI, QRType.CONTACT],
(type: QRType) => {
Text(type)
.fontSize(FontSize.CAPTION)
.fontColor(this.selectedType === type ? Color.White :
AppColors.TEXT_SECONDARY)
.fontWeight(this.selectedType === type ? FontWeight.Medium :
FontWeight.Regular)
.padding({ left: 14, right: 14, top: 6, bottom: 6 })
.borderRadius(9999)
.backgroundColor(this.selectedType === type ?
this.getTypeColor(type) : '#F0F0F0')
.margin({ right: Spacing.SM })
.onClick(() => {
this.selectedType = type;
this.updateQRContent();
})
})
}
.width('100%')
.padding({ left: Spacing.LG, right: Spacing.LG, top: Spacing.MD,
bottom: Spacing.MD })
.backgroundColor(Color.White)
.border({ width: { bottom: 1 }, color: '#F0F0F0' })
Scroll() {
Column() {
Column() {
Row() {
Text('输入内容')
.fontSize(FontSize.CAPTION)
.fontColor(AppColors.TEXT_TERTIARY)
.margin({ bottom: Spacing.SM })
}
.width('100%')
if (this.selectedType === QRType.URL) {
TextInput({ text: this.urlInput, placeholder: '请输入URL链接地址' })
.fontSize(FontSize.BODY)
.width('100%')
.height(44)
.borderRadius(8)
.backgroundColor('#F5F6FA')
.padding({ left: 12, right: 12 })
.onChange((value: string) => {
this.urlInput = value;
this.updateQRContent();
})
}
if (this.selectedType === QRType.TEXT) {
TextArea({ text: this.textInput, placeholder: '请输入任意文本内容' })
.fontSize(FontSize.BODY)
.width('100%')
.height(100)
.borderRadius(8)
.backgroundColor('#F5F6FA')
.padding({ left: 12, right: 12, top: 10, bottom: 10 })
.onChange((value: string) => {
this.textInput = value;
this.updateQRContent();
})
}
if (this.selectedType === QRType.WIFI) {
Column() {
Row() {
Text('网络名称')
.fontSize(FontSize.CAPTION)
.fontColor(AppColors.TEXT_SECONDARY)
.width(60)
TextInput({ text: this.wifiSsid, placeholder: 'WiFi名称' })
.fontSize(FontSize.BODY)
.layoutWeight(1)
.height(40)
.borderRadius(8)
.backgroundColor('#F5F6FA')
.padding({ left: 12, right: 12 })
.onChange((v: string) => { this.wifiSsid = v;
this.updateQRContent(); })
}
.width('100%')
.margin({ bottom: Spacing.SM })
Row() {
Text('密码')
.fontSize(FontSize.CAPTION)
.fontColor(AppColors.TEXT_SECONDARY)
.width(60)
TextInput({ text: this.wifiPassword, placeholder: 'WiFi密码' })
.fontSize(FontSize.BODY)
.layoutWeight(1)
.height(40)
.borderRadius(8)
.backgroundColor('#F5F6FA')
.padding({ left: 12, right: 12 })
.type(InputType.Password)
.onChange((v: string) => { this.wifiPassword = v;
this.updateQRContent(); })
}
.width('100%')
.margin({ bottom: Spacing.SM })
Row() {
Text('加密方式')
.fontSize(FontSize.CAPTION)
.fontColor(AppColors.TEXT_SECONDARY)
.width(60)
Row() {
ForEach(['WPA2', 'WPA', 'WEP', '无'],
(enc: string) => {
Text(enc)
.fontSize(11)
.fontColor(this.wifiEncryption === enc ? Color.White :
AppColors.TEXT_SECONDARY)
.padding({ left: 10, right: 10, top: 4, bottom: 4 })
.borderRadius(9999)
.backgroundColor(this.wifiEncryption === enc ?
'#722ED1' : '#F0F0F0')
.margin({ right: 6 })
.onClick(() => {
this.wifiEncryption = enc;
this.updateQRContent();
})
})
}
}
.width('100%')
}
.width('100%')
}
if (this.selectedType === QRType.CONTACT) {
Column() {
this.ContactField('姓名', this.contactName,
'请输入姓名', (v: string) => { this.contactName = v;
this.updateQRContent(); })
this.ContactField('电话', this.contactPhone,
'请输入电话号码', (v: string) => { this.contactPhone = v;
this.updateQRContent(); })
this.ContactField('邮箱', this.contactEmail,
'请输入邮箱地址', (v: string) => { this.contactEmail = v;
this.updateQRContent(); })
this.ContactField('公司', this.contactCompany,
'请输入公司名称', (v: string) => { this.contactCompany = v;
this.updateQRContent(); })
}
.width('100%')
}
}
.width('100%')
.padding(Spacing.LG)
.backgroundColor(Color.White)
.borderRadius(BorderRadius.MD)
.margin({ left: Spacing.LG, right: Spacing.LG, top: Spacing.LG })
Column() {
Row() {
Text('预览')
.fontSize(FontSize.CAPTION)
.fontColor(AppColors.TEXT_TERTIARY)
Blank()
Row() {
Text('-')
.fontSize(FontSize.TITLE)
.fontColor(AppColors.PRIMARY)
.width(32).height(32)
.borderRadius(16)
.backgroundColor('#F0F0F0')
.textAlign(TextAlign.Center)
.onClick(() => {
if (this.qrSize > 120) {
this.qrSize -= 40;
}
})
Text(`${(this.qrSize / 40).toFixed(0)}x`)
.fontSize(11)
.fontColor(AppColors.TEXT_SECONDARY)
.margin({ left: 8, right: 8 })
Text('+')
.fontSize(FontSize.TITLE)
.fontColor(AppColors.PRIMARY)
.width(32).height(32)
.borderRadius(16)
.backgroundColor('#F0F0F0')
.textAlign(TextAlign.Center)
.onClick(() => {
if (this.qrSize < 320) {
this.qrSize += 40;
}
})
}
}
.width('100%')
.margin({ bottom: Spacing.LG })
QRCode(this.qrContent)
.width(this.qrSize)
.height(this.qrSize)
.backgroundColor(Color.White)
Text(this.getQRDescription())
.fontSize(FontSize.CAPTION)
.fontColor(AppColors.TEXT_TERTIARY)
.margin({ top: Spacing.LG })
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
.width('100%')
.padding(Spacing.XXL)
.backgroundColor(Color.White)
.borderRadius(BorderRadius.MD)
.margin({ left: Spacing.LG, right: Spacing.LG, top: Spacing.LG,
bottom: Spacing.XXL })
.alignItems(HorizontalAlign.Center)
}
.width('100%')
}
.layoutWeight(1)
.scrollBar(BarState.Off)
.backgroundColor('#F5F6FA')
}
.width('100%')
.height('100%')
}
getQRDescription(): string {
switch (this.selectedType) {
case QRType.URL:
return `链接:${this.urlInput.trim() || '(空)'}`;
case QRType.TEXT:
const t = this.textInput.trim();
return t ? `文本内容 (${t.length}字符)` : '(空)';
case QRType.WIFI:
return `WiFi: ${this.wifiSsid} | ${this.wifiEncryption}`;
case QRType.CONTACT:
return `名片: ${this.contactName} | ${this.contactPhone}`;
}
}
@Builder
ContactField(label: string, value: string, placeholder: string,
onChange: (v: string) => void) {
Row() {
Text(label)
.fontSize(FontSize.CAPTION)
.fontColor(AppColors.TEXT_SECONDARY)
.width(40)
TextInput({ text: value, placeholder: placeholder })
.fontSize(FontSize.BODY)
.layoutWeight(1)
.height(40)
.borderRadius(8)
.backgroundColor('#F5F6FA')
.padding({ left: 12, right: 12 })
.onChange(onChange)
}
.width('100%')
.margin({ bottom: Spacing.SM })
}
}
五、二维码的实际应用架构
5.1 App 内展示 + 系统扫码
这是最常见的使用模式:
[App 页面] → QRCode 组件(展示)
↓ 用户拿另一部手机
[系统相机/扫一扫] → 解析 → 跳转/连接/添加联系人
代码侧只需要 QRCode(value)。剩下的全部由手机系统(相机扫码识别)完成。这是"零后端"的场景——二维码是纯客户端技术。
5.2 App 内扫码 + App 内展示
在同一个 App 内完成"生成"和"扫描"的闭环:
// 页面 A:生成二维码
QRCode(this.generateTicketCode())
// 页面 B:扫描二维码(使用 @ohos.scan 扫码能力)
// 扫码完成后在 App 内处理
这种模式常用于:
- 电子票务(电影院 App → 生成门票二维码 → 检票端扫描)
- 共享设备(设备屏幕显示二维码 → App 扫码绑定)
- 身份验证(App 生成身份码 → 另一端扫码认证)
- 文件传输(发送端生成码 → 接收端扫码下载)
5.3 动态二维码 vs 静态二维码
| 静态二维码 | 动态二维码 | |
|---|---|---|
| 编码内容 | 直接嵌入信息(如 URL) | 嵌入短链 ID,指向后端服务 |
| 能否修改 | 生成后不可改 | 后端修改跳转目标即可 |
| 需要后端 | 否 | 是 |
| 典型场景 | WiFi 分享、名片 | 产品追溯、营销活动 |
| 容量需求 | 较大 | 较小(仅需 ID) |
本文 Demo 的四类二维码都是静态二维码——信息直接编码在二维码图案中,不依赖网络或后端服务。扫码端离线也能正常解析。
六、常见面试题 / 踩坑点
6.1 QRCode 的内容长度有限制吗?
有。不同纠错级别和版本的容量不同。作为参考:
- 纯数字:最多 7089 个字符
- 字母数字:最多 4296 个字符
- 二进制(8-bit):最多 2953 个字符
- 中文(UTF-8):最多 ~1800 个字符
如果内容过长,QRCode 组件会自动升级到更高版本来容纳。但注意:版本越高,模块越多,图案越密集,需要的显示尺寸也越大。对于超过 500 字符的内容,建议使用至少 200×200vp 的尺寸。
6.2 为什么我生成的 WiFi 二维码扫了无法连接?
WiFi 格式有严格规范,检查以下几点:
- 字段分隔符必须是分号
; - 末尾必须有
;;(两个分号,最后一个空字段) T:字段值必须是WPA2、WPA、WEP或nopass之一- 如果密码包含特殊字符(如
;、:、\),需要转义:\;、\:、\\
// 正确
'WIFI:T:WPA2;S:MyWiFi;P:12345678;;'
// 错误 — 末尾缺少 ;;
'WIFI:T:WPA2;S:MyWiFi;P:12345678;'
// 错误 — 密码中包含未转义的分号
'WIFI:T:WPA2;S:MyWiFi;P:abc;123;;'
6.3 二维码尺寸该设多大?
参见上文表格。一个简单规则:最小 150vp,推荐 200vp,不要超过屏幕宽度的 70%。
在本文 Demo 中,默认尺寸为 200vp,提供 120~320vp 的调整范围。用户可以按 + / - 按钮缩放,步长 40vp。
6.4 可以给二维码加 Logo 吗?
QRCode 组件本身不支持叠加 Logo。如需"带 Logo 的二维码",有两种方案:
- 在 QRCode 组件上方叠加一个
Stack中的Image,放在中心位置(利用 QR 码的纠错能力,中心区域的图案被遮挡不超过 30% 仍可扫描) - 使用 Canvas 自绘整个二维码 + Logo
方案 1 是最常见的做法——微信、支付宝的收款码都是二维码 + 中心 Logo 的设计。
Stack() {
QRCode(this.content)
.width(200).height(200)
Image($r('app.media.logo'))
.width(40).height(40)
.borderRadius(8)
}
6.5 生成的二维码在深色模式(Dark Mode)下还能扫吗?
默认情况下 QRCode 生成黑色模块 + 透明/白色背景。如果 App 开启了深色模式且整体背景变黑,二维码依然是黑模块 + 透明背景——因为 QRCode 的默认背景色不跟随系统主题变化。
但如果你手动设置了 .backgroundColor(Color.Black),那二维码就"消失"了(黑模块 + 黑背景 = 全黑)。建议始终为 QRCode 显式设置白色背景:
QRCode(this.content)
.backgroundColor(Color.White)
七、总结
QRCode 是 ArkUI 中"从不可能到可能"的组件——与 Rating、Refresh 这类"从手动实现到声明式配置"的组件不同,二维码生成的底层算法复杂度决定了,没有 QRCode 组件就意味着要么引入第三方库,要么放弃在 App 中生成二维码的能力。系统内置 = 零依赖 + 零体积开销 + 与系统扫码体验一致。
1. 一行代码,消灭 1500 行 QR 编码算法。 不需要理解 Reed-Solomon 纠错码、掩码模式、数据位布局——QRCode(value) 就完成了从编码到渲染的全部流程。对于开发者来说,这个组件的存在本身就是最大价值。
2. 内容标准化比组件本身更重要。 WiFi 格式(WIFI:T:...;S:...;P:...;;)、vCard 格式(BEGIN:VCARD...)——这些标准决定了"扫出来是什么效果"。组件负责生成图案,开发者负责生成正确的字符串。
3. 四个参数覆盖 90% 场景。 value(内容)是必填的唯一参数,.width() 和 .height() 控制尺寸,.backgroundColor() 确保对比度。没有多余的 API——因为它们确实不需要。
4. 二维码是"离线"的。 与 API 调用、数据库查询、网络请求不同,二维码编码完全在本地完成——不需要网络、不需要后端、不需要权限。这是它最独特的优势:在完全离线的情况下,仍然能完成信息传递。
QRCode 最合适的应用场景:
- WiFi 分享 / 设备配网(扫码连接,不用输密码)
- 电子名片 / 商务社交(扫码添加联系人)
- URL 跳转 / 应用推广(扫码打开链接)
- 电子票务 / 核销码(扫码验证身份)
- 任何"手机扫一下就能完成操作"的交互
在移动端,二维码已经从"小众技术"变成了"基础设施"。QRCode 组件让这个基础设施可以被任何 ArkUI 开发者免费使用——这是 HarmonyOS 平台能力下沉的又一个典型案例。
更多推荐



所有评论(0)