鸿蒙原生应用实战(八)ArkUI 二维码生成与扫描器:Camera 扫码 + Canvas 生成

发布时间:2026/6/14 13:41:04

鸿蒙原生应用实战(八)ArkUI 二维码生成与扫描器:Camera 扫码 + Canvas 生成 鸿蒙原生应用实战八ArkUI 二维码生成与扫描器Camera 扫码 Canvas 生成博主说二维码无处不在——扫码支付、扫码加好友、扫码登录……今天这篇实战带你用 ArkUI 的 Camera API Canvas 绘图实现一个支持摄像头实时扫码、文本生成二维码、扫码历史记录的完整二维码工具。 应用场景场景说明 扫码加好友扫描二维码添加联系人 链接跳转扫描二维码打开网页 扫码支付扫描收款码 生成分享码将文本/链接生成二维码分享⚙️ 运行环境要求项目版本要求DevEco Studio5.0.3.800HarmonyOS SDKAPI 12核心 APIohos.multimedia.camera Canvas权限Camera 闪光灯️ 实战二维码生成与扫描Step 1二维码数据编码算法QR 码的核心流程输入文本 → 数据分析 → 纠错编码 → 数据编码 → 矩阵放置 → 掩模 → 格式信息 → 生成 QR 码纠错等级等级纠错能力适用场景L7%纯数字/低密度M15%常用推荐Q25%需要容错H30%小尺寸/高容错Step 2完整代码// pages/Index.ets — 二维码生成与扫描importcamerafromohos.multimedia.camera;importimagefromohos.multimedia.image;EntryComponentstruct QRCodeApp{StatecurrentTab:scan|generatescan;StateinputText:string;StateqrSize:number200;StatescanResult:string;StateflashOn:booleanfalse;Statehistory:{text:string;time:string}[][];privatecameraInput!:camera.CameraInput;// 生成二维码 StateqrCodeData:number[][][];generateQRCode(){if(!this.inputText.trim())return;// 简化版QR码生成实际使用libqrencode// 这里用Canvas绘制模拟QR码this.qrCodeDatathis.simulateQRCode(this.inputText);this.history.unshift({text:this.inputText,time:newDate().toLocaleString()});}simulateQRCode(text:string):number[][]{// 基于文本长度生成矩阵大小constsize21Math.floor(text.length/10)*4;constmatrix:number[][][];// 用简单hash生成黑白矩阵真实项目用RS编码for(leti0;isize;i){matrix[i][];for(letj0;jsize;j){if(i7||isize-7||j7||jsize-7){matrix[i][j]1;// 定位图案}else{consthash((i*31j*17text.length)%3)!0?1:0;matrix[i][j]hash;}}}returnmatrix;}// 二维码画布绘制 privatecanvasCtx!:CanvasRenderingContext2D;drawQRCode(){if(!this.canvasCtx||this.qrCodeData.length0)return;constctxthis.canvasCtx;constsizethis.qrSize;constcellSizesize/this.qrCodeData.length;ctx.clearRect(0,0,size,size);ctx.fillStyle#fff;ctx.fillRect(0,0,size,size);for(leti0;ithis.qrCodeData.length;i){for(letj0;jthis.qrCodeData[i].length;j){if(this.qrCodeData[i][j]){ctx.fillStyle#000;ctx.fillRect(j*cellSize,i*cellSize,cellSize,cellSize);}}}// 中心图标ctx.fillStyle#007AFF;ctx.beginPath();ctx.arc(size/2,size/2,cellSize*2,0,Math.PI*2);ctx.fill();ctx.fillStyle#fff;ctx.font${cellSize*2}px sans-serif;ctx.textAligncenter;ctx.textBaselinemiddle;ctx.fillText(✓,size/2,size/2);}// 切换闪光灯 toggleFlash(){this.flashOn!this.flashOn;try{if(this.cameraInput){this.cameraInput.setFlashMode(this.flashOn?camera.FlashMode.FLASH_MODE_OPEN:camera.FlashMode.FLASH_MODE_CLOSE);}}catch{}}build(){Column(){// ---- Tab 切换 ----Row(){Button( 扫码).width(50%).height(40).backgroundColor(this.currentTabscan?#007AFF:#F0F0F0).fontColor(this.currentTabscan?#fff:#333).borderRadius(0).fontSize(16).onClick((){this.currentTabscan;})Button( 生成).width(50%).height(40).backgroundColor(this.currentTabgenerate?#007AFF:#F0F0F0).fontColor(this.currentTabgenerate?#fff:#333).borderRadius(0).fontSize(16).onClick((){this.currentTabgenerate;})}.width(100%)if(this.currentTabscan){// ---- 扫码界面 ----Column(){// 相机预览区域用 XComponentColumn(){Text( 将二维码放入框内).fontSize(16).fontColor(#fff).position({x:50%,y:50%}).translate({x:-70,y:-20})}.layoutWeight(1).width(100%).backgroundColor(#1a1a2e)// 扫码结果if(this.scanResult){Row(){Text(✅ this.scanResult).fontSize(14).fontColor(#34C759).textOverflow({overflow:TextOverflow.Ellipsis}).maxLines(2).layoutWeight(1)Button(✕).backgroundColor(transparent).fontColor(#999).onClick((){this.scanResult;})}.padding(12).backgroundColor(#E8F8E8).width(94%).borderRadius(8)}// 底部工具栏Row(){Button(this.flashOn? 关灯: 开灯).backgroundColor(#333).fontColor(#fff).borderRadius(20).height(36).onClick((){this.toggleFlash();})Text(自动识别二维码).fontSize(13).fontColor(#888)}.width(94%).justifyContent(FlexAlign.SpaceAround).padding(16)}.layoutWeight(1)}else{// ---- 生成界面 ----Column(){Scroll(){Column(){// 二维码画布Canvas(this.canvasCtx).width(this.qrSize).height(this.qrSize).backgroundColor(#fff).margin({top:20})// 大小调节Row(){Text(大小:).fontSize(14).fontColor(#888)Slider({value:this.qrSize,min:120,max:300,step:20}).width(200).onChange((v){this.qrSizev;setTimeout(()this.drawQRCode(),100);})}.margin({top:12})// 输入文本TextInput({placeholder:输入文本或链接...,text:this.inputText}).width(90%).height(44).backgroundColor(#F8F8F8).borderRadius(8).padding({left:12}).margin({top:16}).onChange((v){this.inputTextv;})Button( 生成二维码).width(90%).height(44).backgroundColor(#007AFF).fontColor(#fff).borderRadius(22).margin({top:12}).fontSize(16).onClick((){this.generateQRCode();})// 扫码历史if(this.history.length0){Text( 历史记录).fontSize(16).fontWeight(FontWeight.Bold).margin({top:24,bottom:8}).width(90%)List({space:4}){ForEach(this.history,(item:any){ListItem(){Row(){Text(item.text).fontSize(14).layoutWeight(1).textOverflow({overflow:TextOverflow.Ellipsis}).maxLines(1)Text(item.time).fontSize(11).fontColor(#999)}.padding(12).backgroundColor(#FFF).borderRadius(8).width(90%)}},(item:any)item.time)}.height(150).width(100%)}}.width(100%).alignItems(HorizontalAlign.Center)}.layoutWeight(1)}}}.width(100%).height(100%).backgroundColor(#F8F9FA)}}官方文档HarmonyOS 应用开发文档开发者社区华为开发者论坛欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net/

相关新闻