HarmonyOS 7 鸿蒙电脑跨屏窗口:负坐标不是异常,弹层怎样裁剪到当前显示区域
·

HarmonyOS 7 鸿蒙电脑跨屏窗口:负坐标不是异常,弹层怎样裁剪到当前显示区域
外接屏放在主屏左侧,坐标可能为负。把所有x强制钳到0,会把弹层直接推回主屏。需要先明确坐标系,再求窗口与所在显示区域的交集。
适配范围
所有输入必须在同一全局坐标系和同一单位中。裁剪结果不是可直接传给任意ArkUI布局属性的vp值;窗口局部坐标转换和显示密度换算在适配层完成。系统是否允许弹层越界也需要按窗口类型验证。
案例一
副屏在主屏左侧:负x合法,只裁掉超出副屏的80像素,不把整个弹层移到0。
案例二
窗口跨越两块屏:对当前显示区域求交集。没有交集返回null,由上层决定迁移、关闭或重新定位。
可以运行的实现
export function clipRect(rect, display) {
for (const r of [rect,display]) if (![r.x,r.y,r.w,r.h].every(Number.isFinite) || r.w < 0 || r.h < 0) throw Error('invalid_rect');
const x = Math.max(rect.x,display.x), y = Math.max(rect.y,display.y);
const right = Math.min(rect.x + rect.w,display.x + display.w);
const bottom = Math.min(rect.y + rect.h,display.y + display.h);
if (right <= x || bottom <= y) return null;
return {x,y,w:right-x,h:bottom-y};
}
复现与断言
把实现与以下测试放进同一个example.mjs,执行node example.mjs。断言失败会报错,全部通过正常退出。这些断言已经在本地Node.js执行;它们不代表SDK编译、真机接口调用或性能实测已经通过。
import assert from 'node:assert/strict';
const left = {x:-1920,y:0,w:1920,h:1080};
assert.deepEqual(clipRect({x:-2000,y:20,w:300,h:200},left),{x:-1920,y:20,w:220,h:200});
assert.equal(clipRect({x:10,y:20,w:100,h:100},left),null);
assert.deepEqual(clipRect({x:-100,y:1000,w:200,h:200},left),{x:-100,y:1000,w:100,h:80});
assert.throws(() => clipRect({x:0,y:0,w:-1,h:2},left));
方案取舍
钳到0隐含主屏原点假设;按显示区域裁剪支持负原点与上下排列。与把整个窗口缩小相比,交集只描述可见部分,不改变原窗口尺寸。
接入时别漏掉这些边界
所有输入必须在同一全局坐标系和同一单位中。裁剪结果不是可直接传给任意ArkUI布局属性的vp值;窗口局部坐标转换和显示密度换算在适配层完成。系统是否允许弹层越界也需要按窗口类型验证。
复用时把输入获取与纯逻辑分开:界面、系统事件和服务请求负责取得真实输入,独立模块负责给出判断或保存状态。保留上述两个案例作为回归测试,并对失败原因记录最少必要日志,不记录文件内容、账号凭据或其它敏感数据。升级SDK后重新核对支持设备、接口版本与错误行为,而不是只改目标版本号。
官方资料
示例验证环境为Node.js,验证范围是应用侧逻辑。本文不将示例当作系统接口接入代码;具体接口的支持设备、最低版本和调用方式,以所用SDK对应的官方文档为准。
更多推荐




所有评论(0)