news 2026/9/27 7:33:14

〖共创稿事节〗HarmonyOS 7 新特性实战(09):碰一碰事件、坐标命中与显式分享接入

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
〖共创稿事节〗HarmonyOS 7 新特性实战(09):碰一碰事件、坐标命中与显式分享接入

手机里选好一张展品卡,在平板展板的某个区域碰一下,卡片就落到那里。这个流程包含两种不同结果:文件已经传到接收端,以及文件被放进用户指定的位置。前者成功而后者错位,用户仍会认为这次分享失败。

接收端需要同时处理内容、坐标和事务状态。方案以单张展品卡为例,使用系统精准分享能力传递资源与实际触碰位置,应用负责把系统坐标转换为展板位置,并保证同一分享只提交一次。

坐标的参考系必须来自接口合同

触碰坐标究竟相对屏幕、窗口还是内容区,单位是物理像素还是逻辑尺寸,需要从真实系统事件定义确认。状态栏、窗口边框、旋转和缩放都可能造成偏差,不能看到 x/y 字段就直接传给卡片布局。

将变换拆成屏幕到窗口、窗口到画布两步更容易排查。画布还有平移缩放时,使用逆变换得到内容坐标。以下只描述应用的几何计算,不代表系统一定返回屏幕像素:

interfacePoint{x:number;y:number;}interfaceCanvasTransform{originX:number;originY:number;scale:number;}functiontoCanvas(p:Point,t:CanvasTransform):Point{if(!Number.isFinite(t.scale)||t.scale<=0){thrownewError('Invalid canvas scale');}return{x:(p.x-t.originX)/t.scale,y:(p.y-t.originY)/t.scale};}

所有输入点和偏移还应检查有限性。系统事件进入平台适配层时就附上参考系标识,避免后续页面猜测来源。

落点选择与文件传输分开推进

接收文件可能比坐标事件晚。接收端可以先显示待接收位置,但不要立即把正式卡片写入目录。资源可读、格式检查通过之后,再完成落点提交;失败则撤销占位并显示原因。

应用记录应包括 transferId、资源临时路径、目标展板、内容坐标和状态。若坐标越出画布,允许用户重新选点或放入待整理区,不要静默把内容丢到某个默认角落。

多窗口情况下,目标展板也要稳定标识。传输期间用户切换到另一个展板,最终卡片仍属于原请求,或进入明确的重新确认流程,不能依赖“当前活动页面”做提交。

用一次提交处理重复回调

弱连接和跨设备流程可能发生重试。应用用稳定 transferId 保存提交结果,再次收到相同传输时返回已有结果。文件哈希可用于内容校验,但不能代替业务传输 ID:用户可能合法地把同一张图放进两个不同位置。

收到请求 → 等待资源 → 检查格式与大小 → 确定落点 → 提交展板记录 → 记录 transferId → 返回结果

资源复制与数据库更新需要设计失败补偿。记录写入失败时清除本次临时复制;记录已经成功但回执丢失时保留结果,让重试查到它。避免把“没有收到成功提示”当作“应该再插入一张”。

临时 URI 的寿命不要穿透到长期收藏

跨设备传来的 URI 可能只在授权范围和生命周期内有效。需要长期展示的卡片,应在有权读取时复制到自己的资源目录,并验证完整性,再保存应用自己的引用。

图片还需检查尺寸与解码成本,不能只限制压缩文件字节数。极高分辨率小文件也可能带来较大解码内存。拒绝时说明是格式、大小还是解码失败,不把所有错误都归结为“碰一碰失效”。

用网格图验收精度

第一版 Demo 在接收端显示编号网格,手机发送一张带明显边界的测试图。分别在左上、中央、右下触碰,记录系统原始坐标、变换后坐标与最终槽位。窗口移动、画布缩放、横竖屏切换后重复实验。

双端录屏应能对应同一 transferId。还要验证取消、断连和重复接收,不以单次中间位置成功代表全部坐标都正确。若某类设备不提供精准位置,则提供普通接收后手动放置路径,并明确区分两种操作。

用一个算得出的落点定位偏移错误

假设平台适配后得到窗口逻辑坐标 (260,180),画布原点为 (20,40),缩放为 2,则内容坐标应为 (120,70)。这是人工构造的数学用例:如果实际界面落在 (130,90),说明遗漏了原点扣除,不能通过挪动卡片边距修补。

收件方式使用条件交互代价
精准坐标直接落位来源坐标系已确认,资源有效需处理变换和越界
接收后手动选位设备不支持位置或坐标无效多一次操作,但位置可确认

先完成变换与越界测试,再加入资源提交及重复回执,最后用成对设备核对三个网格点。提交记录和 transferId 应在同一事务中生效;仅按流程先后分别写两条记录,仍可能在中断时产生重复卡片。

参考:精准分享官方解读、HarmonyOS 7 能力入口。

监听注册、坐标命中与临时分享目标

坐标必须和渲染区域使用同一单位。图鉴卡片在布局变化时重新记录全局区域,把 ArkUI 的 vp 转为 px;负坐标、空区域和重叠区域没有唯一命中。真实触碰只建立候选分享目标,用户点击分享按钮后才调用系统分享。

触碰回调注册、同一函数解除监听和一次性使用目标对象已接入。离页及切换主题时解除监听,页面生命周期编号拦截迟到回调。

exportclassKnockProbe{privateactive:boolean=false;privateregions:HitRect[]=[];setRegions(regions:HitRect[]):void{this.regions=regions.slice();}privatepending:harmonyShare.SharableTarget|undefined=undefined;privatecallback:(target:harmonyShare.SharableTarget)=>void=()=>{};start(report:(message:string)=>void):void{if(this.active){return;}this.callback=(target:harmonyShare.SharableTarget):void=>{if(!this.active){return;}this.pending=target;constcoordinate:harmonyShare.CoordinateInfo|undefined=target.getInfo().coordinate;consthit:string|undefined=coordinate?TouchSelection.pick(coordinate.screenX,coordinate.screenY,this.regions):undefined;report('命中区域:'+(hit||'无唯一命中,请手动选择')+'; '+(coordinate?'真实触碰坐标 px: '+coordinate.screenX+', '+coordinate.screenY:'收到触碰,系统未提供坐标'));};this.active=true;try{harmonyShare.on('knockShare',this.callback);}catch(error){this.active=false;throwerrorasError;}}asyncshareSelected():Promise<void>{consttarget:harmonyShare.SharableTarget|undefined=this.pending;if(!target){thrownewError('先等待真实触碰事件');}this.pending=undefined;awaittarget.share(newsystemShare.SharedData({utd:'general.plain-text',content:'玄龟 · 山海图鉴实验',title:'玄龟'}));}stop():void{if(!this.active){return;}harmonyShare.off('knockShare',this.callback);this.active=false;this.pending=undefined;}}

辅助校验与边界处理使用以下实现:

exportinterfaceHitRect{id:string;left:number;top:number;width:number;height:number;}exportclassTouchSelection{staticpick(x:number,y:number,regions:HitRect[]):string|undefined{if(!Number.isFinite(x)||!Number.isFinite(y)||x<0||y<0){returnundefined;}consthits:HitRect[]=regions.filter((rect:HitRect)=>{return[rect.left,rect.top,rect.width,rect.height].every((n:number)=>Number.isFinite(n))&&rect.width>0&&rect.height>0&&x>=rect.left&&y>=rect.top&&x<rect.left+rect.width&&y<rect.top+rect.height;});// Ambiguous/overlapping regions require explicit user selection.returnhits.length===1?hits[0].id:undefined;}}

用坐标和重复回调核对源码

真机触碰坐标与布局单位对应、接收设备实际收到文本。

检查层当前处理不能替代的结果
编译API 26 工程进行类型检查与打包目标设备支持
逻辑校验输入、状态或资源释放边界平台服务真实返回
联调按上面的输入和条件逐步执行不能以按钮文案代替核心结果

API 26 验证边界

2026-09-23 已在 API 26 模拟器安装并启动本工程,基础实验首页可见;进入包含精准分享适配器的设备专项页后,进程被系统终止,当前日志没有给出可归因的 Kit 缺失栈。随后为本工程配置包名匹配的调试签名,签名 HAP 已安装到 HBN-AL80 真机,DeviceLabPage可见;“监听真实碰一碰”返回“已注册监听,等待真实触碰”,“解除监听”返回“监听已解除”。这确认了本应用在该真机上的监听注册与释放链路。

现有记录没有knockShare的真实回调、系统坐标或跨设备接收文本:模拟器不能替代第二台物理碰一碰设备。因此模拟器运行、监听成功和宿主测试都不能作为物理碰一碰传输成功的依据。

2026-09-23 补充把同一签名 HAP 部署到 API 26 模拟器和 HBN-AL80,两个目标均能启动基础实验首页;模拟器打开设备专项页后仍被系统终止,因而没有把它写成专项页或系统分享成功。宿主测试直接加载实际KnockProbe与TouchSelection源码,以平台 Kit 测试替身验证:负坐标、右边界与重叠区域不命中;重复start只注册一次;stop使用同一回调;分享目标仅能消费一次。这构成同包双端部署和应用逻辑联调,不构成物理碰一碰传输。完整设备、构建与测试记录见 完整设备、构建与测试记录。后续物理验收仍需具备系统能力的真实受端,再记录同一传输的原始坐标、命中区域和接收内容。

碰一碰事件、坐标与分享接口的版本约束,以 HarmonyOS 官方文档中心和当前 SDK 声明为准。

触碰边界与重复监听

矩形右边界采用半开区间,重叠命中不选择任何条目。测试也检查监听只注册一次、注销使用同一回调,以及分享目标只消费一次。宿主测试直接载入 KnockProbe 与 TouchSelection,仅以替身代替系统分享 Kit;load 与 test 属于测试框架。

test('touch: negative, right boundary and overlap are not unique hits',()=>{consta={id:'a',left:10,top:10,width:20,height:20};assert.equal(TouchSelection.pick(10,10,[a]),'a');assert.equal(TouchSelection.pick(30,20,[a]),undefined);assert.equal(TouchSelection.pick(-1,10,[a]),undefined);assert.equal(TouchSelection.pick(20,20,[a,{...a,id:'b'}]),undefined);});test('touch: register once and release exact callback; do not invent events',async()=>{letcb,on=0,off=0,shared=0;constkit={on(e,c){on++;cb=c;},off(e,c){assert.equal(c,cb);off++;}};constC=load('services/KnockProbe',{'@kit.ShareKit':{harmonyShare:kit,systemShare:{SharedData:class{constructor(record){this.record=record;}}}}}).KnockProbe;constx=newC();awaitassert.rejects(x.shareSelected());x.start(()=>{});x.start(()=>{});assert.equal(on,1);cb({getInfo:()=>({coordinate:{screenX:-1,screenY:-1}}),share:async()=>shared++});awaitx.shareSelected();awaitassert.rejects(x.shareSelected());x.stop();x.stop();assert.equal(off,1);assert.equal(shared,1);});
操作或边界应检查的结果
输入不满足前提不调用后续平台操作
平台拒绝或抛错保留错误,不生成成功状态
再次进入或重试检查旧状态不会污染新任务
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 7:27:02

Jev 能否用于银行风控?从规则引擎到语义决策层

在银行和消费金融领域&#xff0c;Blaze、Drools 等规则引擎已经使用多年。无论贷前授信、贷中风险监控&#xff0c;还是贷后逾期管理&#xff0c;本质上都存在大量“根据客户状态进行判断&#xff0c;再选择下一步策略”的业务逻辑。例如贷后催收系统通常会根据逾期天数、逾期…

作者头像 李华
网站建设 2026/9/27 7:22:15

wgpu 完全指南:4步跑通60fps的跨平台图形管线

wgpu 完全指南&#xff1a;4步跑通60fps的跨平台图形管线 【免费下载链接】wgpu A cross-platform, safe, pure-Rust graphics API. 项目地址: https://gitcode.com/GitHub_Trending/wg/wgpu 把三角形数量推到10万&#xff0c;帧率从60掉到18&#xff0c;你多半会怀疑是…

作者头像 李华
网站建设 2026/9/27 7:20:22

好用的全屋定制公司

在上海找全屋定制&#xff0c;很多业主都有过类似的经历&#xff1a;跑遍大大小小的门店&#xff0c;报价单看得眼花缭乱&#xff0c;好不容易定下来&#xff0c;安装时却发现板材不对版、封边粗糙、柜体与墙体之间留着尴尬的缝隙。更让人头疼的是&#xff0c;出了问题找售后&a…

作者头像 李华