
电脑上两个人玩双人24点,鼠标轮流点击不够顺手。给两位玩家分配键盘区域以后,还需要处理按住键、切换窗口和重新回到应用:一次按键只能执行一次动作,焦点回来后也不能把旧的按下状态继续算进去。
《拼棋派对》把键盘事件集中到gameRoot,再按当前玩法分发。本篇分析KeyDown与KeyUp、修饰键过滤、按键集合和窗口焦点通知。代码对应1.0.19,GIF采用此前电脑模拟器的实际键盘操作记录,属于历史证据。
本文目录
先把事件送到正确页面
根组件设置id、可聚焦和onKeyEvent。handleNumberKey先检查activeTab是否为play,再按activeMode分发到1024、反应抢点或电脑双人24点。
typescript
.id('gameRoot')
.focusable(true)
.onKeyEvent((event: KeyEvent) => this.handleNumberKey(event))
让所有页面都无条件响应字母键,会影响设置、目录和输入框。玩法入口限定比每个按钮自己监听键盘更容易检查范围。双人24点还检查isDesktopDevice,手机外接键盘不因此自动得到同一套桌面操作策略。
事件分发也过滤Ctrl和Alt组合键,避免系统快捷键顺带触发走棋。过滤应在执行玩法动作之前发生;动作已经改了状态后再stopPropagation,不能撤销错误操作。
按下去重,抬起释放
操作系统可能在长按时重复发送KeyDown。项目用heldKeyCodes记住已经按住的键,处理前检查集合,KeyUp时删除。
typescript
if (event.type === KeyType.Up) {
this.heldKeyCodes.delete(event.keyCode);
return;
}
if (event.type !== KeyType.Down) {
return;
}
具体玩法检查heldKeyCodes.has,第一次执行才add。双人24点只有dispatchDuel24Key识别的键才加入集合,其他键返回false。这样普通无关键不会改变游戏状态。
去重和防抖不是一回事。这里要等同一物理按键抬起,才允许下次动作;不能只等待100毫秒,否则一直按着仍会周期性提交。反应抢点尤其需要避免长按自动累计多分。
为双方保留明确映射
双人24点将A、B映射到各自牌槽、运算符、撤销、清空和提交。比如B的7、8、9、0对应四个牌槽,U、I、O、P对应加减乘除,J提交、K撤销、Y清空。
typescript
if (code === KeyCode.KEYCODE_7) {
this.handleDuel24SlotTap('B', 0);
return true;
}
if (code === KeyCode.KEYCODE_J) {
this.submitDuel24('B');
return true;
}
键盘和触摸共用同一业务函数,规则校验继续放在函数内。不要为了快捷键复制一份合并或计分代码,否则按钮修复了除零,键盘分支却可能仍有旧错误。
布局上的左右位置不是玩家身份。窗口变化、面板重排和焦点切换后,键位仍然指向同一player。页面提示应能帮助玩家找到自己的一组操作,不能只在文章里给映射。
失焦后清理并恢复
按住键切到其他窗口,应用可能收不到KeyUp。若集合不清理,回来再按同一个键会一直被误认为仍按着。项目在onPageHide、onPageShow和窗口焦点信号变化时清空集合。
typescript
private onWindowFocusSignal(): void {
this.heldKeyCodes.clear();
const active = AppStorage.get<boolean>('windowFocusActive');
if (active === true) {
this.restoreGameFocus();
}
}
EntryAbility注册windowStageEvent,写入windowFocusActive与递增的windowFocusEpoch。页面通过StorageProp和Watch接收变化,再请求gameRoot焦点。计数代数能让多次焦点事件持续触发,避免布尔值重复写入却没有新通知。
窗口监听需要在销毁时注销,引用也清空,避免旧窗口对象继续发通知。页面显示时恢复焦点,并不代表所有子控件都不会再次夺走焦点;1024还在棋盘点击时请求自己的number-board焦点。
实际效果与回归边界
下面保留此前电脑模拟器的键盘操作:执行合并、撤销,并观察Ctrl/Alt组合键不改变牌面。它用于说明已有输入分支,素材不是本轮新拍。

真正回归时应从一个非初始局面开始,按住操作键、切换窗口、松手、切回,再按同键,检查只执行一次。还应覆盖A/B连续操作、重开后的旧键、点击工具后的焦点和最大化窗口。
这些情况不能靠静态截图证明。本系列没有在本轮重开电脑模拟器完成全部焦点回归,因此文章把源码机制和历史操作效果分开说明。后续产品修改后应对同一签名包重新验证。
键盘适配的目标是让输入归属和次数可靠。事件能收到只是第一步,处理完长按与失焦,双人键位才适合持续使用。
源码入口:entryability/EntryAbility.ets 的窗口焦点监听;pages/Index.ets 的 handleNumberKey、handleDuel24Key、dispatchDuel24Key、onWindowFocusSignal。参考HarmonyOS官方文档。