一、引言

二维码已经渗透到日常生活的每个角落。扫码支付、扫码加好友、扫码连接 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(最常见)、WEPnopass(无密码)
  • P: 后是密码(如果 T:nopass 则省略此字段)
  • 末尾的 ;; 是格式要求的结束标记

不同扫码 App 对这些格式的支持程度不同,但 URL、文本、电话和邮件是通用标准。
在这里插入图片描述

三、Demo 设计:二维码生成器

3.1 功能概述

Demo 是一个二维码生成器页面,模拟实际 App 中的"分享二维码"或"扫码加好友"功能:

  1. 5 种内容类型预设:网址、文本、电话、邮箱、WiFi——用户点击预设按钮快速切换
  2. 实时生成:二维码随输入内容变化实时更新
  3. 前景色选择器:8 种预设颜色(黑、蓝、绿、红、粉、橙、紫、青)供用户选择
  4. 背景色选择器:7 种背景色(白、灰、暖黄、浅绿、浅蓝、浅粉、黑)供用户选择
  5. 尺寸调节:三种预设尺寸(150×150、200×200、250×250)
  6. 实时预览:二维码放大显示在页面中央,当前内容类型在下方标注

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 内部完成。

核心要点回顾:

  1. QRCode 是"字符串 → 像素矩阵"的转换器:构造函数接收字符串,内部完成 QR Code 标准的全部编码流程,输出可扫描的二维码图案。开发者不需要理解 QR Code 的编码算法。

  2. color 和 backgroundColor 是唯二的外观控制方法:前景色控制二维码模块的颜色,背景色控制底层背景。两者之间需要足够的对比度以保证可扫描性。

  3. 声明式更新是 QRCode 的核心使用模式:绑定 @State 变量到构造函数和样式方法,变量变化时二维码自动重新生成。结合 TextInput 的 onChange 即可实现输入内容实时生成二维码。

  4. 不同内容格式决定扫码行为:URL(打开网页)、tel(拨号)、mailto(发邮件)、WiFi(连接网络)——QRCode 只负责生成图案,格式的正确性由开发者保证。

  5. 二维码尺寸应在 100~250vp 之间:太小难以扫描,太大浪费空间。200vp 是大多数场景的最佳选择。

  6. 安全性不容忽视:二维码内容对扫描者完全透明。在二维码下方标注内容摘要、避免在二维码中编码敏感信息——是开发者的基本责任。

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 完成最常见的任务。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐