HarmonyOS ArkUI QRCode 与 PatternLock:二维码生成与手势密码
·
系列:鸿蒙 HarmonyOS 6.1 新特性实战 · 第 42 篇
QRCode 和 PatternLock 是 ArkUI 面向安全与分享场景的两个专用组件。QRCode 可将任意字符串实时渲染为二维码图像,PatternLock 则提供九宫格手势密码交互,常用于应用锁、支付验证等场景。本篇演示如何组合使用这两个组件,并实现颜色切换与密码设置完整流程。
运行效果
初始状态(QRCode 展示 + PatternLock 待绘制): 
切换颜色后的 QR 码与完成手势绘制: 
QRCode 二维码生成
QRCode 组件接收任意字符串作为内容参数,自动编码并渲染为标准二维码。内容可以是 URL、纯文本、JSON 字符串等任意格式。
@State qrContent: string = 'https://developer.huawei.com'
@State qrColor: string = '#000000'
@State qrBgColor: string = '#ffffff'
QRCode(this.qrContent)
.width(200)
.height(200)
.color(this.qrColor)
.backgroundColor(this.qrBgColor)
.color() 控制前景色(码点颜色),背景色建议保持白色以确保扫码兼容性。动态修改 qrContent 绑定的状态变量即可实时更新二维码内容。
颜色切换示例:
private colorOptions: string[] = ['#000000', '#0066ff', '#e74c3c', '#27ae60']
@State selectedColor: number = 0
Row({ space: 12 }) {
ForEach(this.colorOptions, (color: string, index: number) => {
Column()
.width(28)
.height(28)
.borderRadius(14)
.backgroundColor(color)
.border({
width: this.selectedColor === index ? 3 : 1,
color: this.selectedColor === index ? '#0066ff' : '#dddddd'
})
.onClick(() => {
this.selectedColor = index
this.qrColor = color
})
})
}
PatternLock 手势密码
PatternLock 渲染九宫格圆点,用户滑动连线设置或验证手势密码。通过 PatternLockController 控制器可以在代码中重置绘制状态。
private patternController: PatternLockController = new PatternLockController()
@State patternResult: string = ''
@State savedPattern: number[] = []
@State isConfirmStep: boolean = false
@State firstInput: number[] = []
PatternLock(this.patternController)
.sideLength(240)
.circleRadius(10)
.pathColor('#0066ff')
.onPatternComplete((input: number[]) => {
this.handlePatternComplete(input)
})
sideLength:九宫格整体边长(px),决定组件大小circleRadius:每个圆点的半径pathColor:连线颜色onPatternComplete:绘制完成后触发,input为经过的圆点序号数组(1-9,左上至右下排列)
两步密码设置流程
实际场景中,密码设置需要两次确认。以下实现“首次输入 → 确认输入“的完整流程:
handlePatternComplete(input: number[]): void {
if (input.length < 4) {
this.patternResult = '图案太短,至少连接 4 个点'
this.patternController.reset()
return
}
if (!this.isConfirmStep) {
// 第一步:记录初始图案
this.firstInput = input
this.isConfirmStep = true
this.patternResult = '请再次绘制确认图案'
this.patternController.reset()
} else {
// 第二步:比对两次输入
const match = this.firstInput.length === input.length &&
this.firstInput.every((v: number, i: number) => v === input[i])
if (match) {
this.savedPattern = input
this.patternResult = `密码设置成功!路径:${input.join('-')}`
} else {
this.patternResult = '两次图案不一致,请重新设置'
this.firstInput = []
this.isConfirmStep = false
}
this.patternController.reset()
}
}
重置按钮:
Button('重新设置')
.fontSize(14)
.onClick(() => {
this.isConfirmStep = false
this.firstInput = []
this.savedPattern = []
this.patternResult = ''
this.patternController.reset()
})
完整代码
@Entry
@Component
struct QRCodePatternPage {
@State qrContent: string = 'https://developer.huawei.com'
@State qrColor: string = '#000000'
@State selectedColor: number = 0
@State patternResult: string = '请绘制手势密码(至少 4 个点)'
@State savedPattern: number[] = []
@State isConfirmStep: boolean = false
@State firstInput: number[] = []
private patternController: PatternLockController = new PatternLockController()
private colorOptions: string[] = ['#000000', '#0066ff', '#e74c3c', '#27ae60']
handlePatternComplete(input: number[]): void {
if (input.length < 4) {
this.patternResult = '图案太短,至少连接 4 个点'
this.patternController.reset()
return
}
if (!this.isConfirmStep) {
this.firstInput = input
this.isConfirmStep = true
this.patternResult = '请再次绘制确认图案'
this.patternController.reset()
} else {
const match = this.firstInput.length === input.length &&
this.firstInput.every((v: number, i: number) => v === input[i])
if (match) {
this.savedPattern = input
this.patternResult = `密码设置成功!路径:${input.join('-')}`
} else {
this.patternResult = '两次图案不一致,请重新设置'
this.firstInput = []
this.isConfirmStep = false
}
this.patternController.reset()
}
}
build() {
Scroll() {
Column({ space: 24 }) {
Text('二维码生成').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#333333')
// 内容输入
TextInput({ text: this.qrContent, placeholder: '输入二维码内容' })
.width('100%')
.fontSize(13)
.onChange((val: string) => { this.qrContent = val })
// 颜色选择
Row({ space: 12 }) {
Text('前景色:').fontSize(13).fontColor('#666666')
ForEach(this.colorOptions, (color: string, index: number) => {
Column()
.width(28).height(28).borderRadius(14)
.backgroundColor(color)
.border({
width: this.selectedColor === index ? 3 : 1,
color: this.selectedColor === index ? '#0066ff' : '#dddddd'
})
.onClick(() => {
this.selectedColor = index
this.qrColor = color
})
})
}
// 二维码展示
QRCode(this.qrContent)
.width(200).height(200)
.color(this.qrColor)
.backgroundColor('#ffffff')
Divider().strokeWidth(1).color('#eeeeee')
// 手势密码
Text('手势密码设置').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#333333')
Text(this.isConfirmStep ? '第二步:确认图案' : '第一步:绘制图案')
.fontSize(12).fontColor('#999999')
Text(this.patternResult)
.fontSize(14)
.fontColor(this.savedPattern.length > 0 ? '#27ae60' : '#e74c3c')
.textAlign(TextAlign.Center)
PatternLock(this.patternController)
.sideLength(240)
.circleRadius(10)
.pathColor('#0066ff')
.onPatternComplete((input: number[]) => {
this.handlePatternComplete(input)
})
Button('重新设置')
.fontSize(14)
.backgroundColor('#f5f5f5')
.fontColor('#333333')
.onClick(() => {
this.isConfirmStep = false
this.firstInput = []
this.savedPattern = []
this.patternResult = '请绘制手势密码(至少 4 个点)'
this.patternController.reset()
})
}
.width('100%')
.padding(24)
}
.width('100%')
.height('100%')
.backgroundColor('#f8f8f8')
}
}
API 速查
| 属性/方法 | 说明 |
|---|---|
QRCode(content) |
传入字符串内容,自动生成二维码 |
.color(color) |
二维码前景色(码点颜色) |
.backgroundColor(color) |
二维码背景色,建议保持白色 |
PatternLock(controller) |
创建九宫格手势密码,绑定控制器 |
.sideLength(px) |
九宫格整体边长(像素) |
.circleRadius(px) |
圆点半径 |
.pathColor(color) |
连线颜色 |
.onPatternComplete(fn) |
绘制完成回调,参数为圆点序号数组(1-9) |
PatternLockController.reset() |
清除当前绘制,恢复初始状态 |
Array.every(fn) |
检查所有元素是否满足条件,用于路径比对 |
小结
- QRCode 内容可以是任意字符串;前景色可自定义,但背景色建议保持白色以确保主流扫码 App 兼容
- 修改绑定的
@State变量后,QRCode 会自动重新渲染,无需手动刷新 - PatternLock 圆点编号 1-9,从左上角到右下角依次排列,与手机拨号键盘布局一致
- 最短路径建议设为 4 个点,安全性与易用性较为均衡
patternController.reset()在每次onPatternComplete回调结束后调用,清除绘制痕迹- 两步密码设置流程中,使用
Array.every()逐位比对路径数组是最简洁的方式
上一篇:Search 搜索框实战 | 下一篇:Marquee 跑马灯与 Gauge 仪表盘
更多推荐




所有评论(0)