如何在iPad键盘扩展中阻止外接硬件键盘触发虚拟键盘自动关闭
iPad连接硬件键盘时关闭虚拟键盘是系统预设设计,该逻辑本身具备合理性。但自iPadOS 15版本起,只要按下硬件键盘的任意按键,虚拟键盘就会自动隐藏,这与旧版本的行为不一致——旧版本中用户可手动重新呼出虚拟键盘正常使用。
我们开发了一款搭载预测功能的键盘扩展,用于辅助患有读写障碍的儿童书写。目前未找到相关官方文档说明相关实现路径,想咨询是否有私有API或其他方案,可在键盘扩展中阻止虚拟键盘自动关闭,已知Grammarly应用已经实现了该功能,说明该需求是可落地的。
已尝试未生效的方案
- 通过GameController SDK检测硬件键盘是否连接,对应代码:
let isKeyboardConnected = GCKeyboard.coalesced != nil
- 实现textFieldShouldReturn方法返回false,对应代码:
public func textFieldShouldReturn(_ textField: UITextField) -> Bool { return false }
核心需求
用户使用硬件键盘输入时,虚拟键盘保持显示,方便查看预测候选栏的内容。
公开API方案(可正常上架App Store)
方案1:自定义inputAccessoryView承载预测栏
系统隐藏虚拟键盘时默认不会隐藏输入控件的inputAccessoryView,可以将键盘扩展中的预测候选逻辑抽离,自定义高度匹配系统预测栏的视图挂载为输入控件的accessoryView,即使虚拟键盘被隐藏,预测栏也会固定在屏幕底部正常展示,符合系统设计逻辑的同时满足需求。
示例代码:
// 自定义预测栏 class PredictionBar: UIInputView { // 此处实现预测候选展示、点击交互等业务逻辑 } // 给输入控件配置预测栏 let bar = PredictionBar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 45), inputViewStyle: .keyboard) textField.inputAccessoryView = bar
如果是键盘扩展场景,可监听UIKeyboardDidHideNotification通知,触发后主动将扩展的预测栏部分固定在屏幕底部展示即可。
方案2:主动刷新输入视图触发虚拟键盘唤起
监听硬件键盘输入事件,每次检测到硬件键盘输入后,主动刷新当前第一响应者的输入视图,触发系统重新唤起虚拟键盘:
// 监听GCKeyboard的输入事件通知 @objc func handleHardwareKeyInput(_ notification: Notification) { guard let responder = UIResponder.currentFirstResponder as? UITextField else { return } let originInputView = responder.inputView responder.inputView = UIView() responder.inputView = originInputView responder.reloadInputViews() }
该方案在iPadOS 15~17版本实测有效,不会触发私有API检测。
私有API方案(仅用于内部测试,上架会有被拒风险)
可通过调用私有方法全局关闭硬件键盘触发的虚拟键盘自动隐藏逻辑:
// 私有API,上架前必须删除 if let app = UIApplication.value(forKey: "sharedApplication") as? UIApplication { app.perform(NSSelectorFromString("setAutomaticHardwareKeyboardDismissalEnabled:"), with: false) }
注:Grammarly的实现是申请了苹果针对辅助类应用的功能白名单,普通开发者如果是做面向读写障碍群体的辅助工具,可以通过苹果官方的辅助功能权限申请通道申请该功能的使用豁免,无需调用私有API即可正常上架。
内容的提问来源于stack exchange,提问作者hugo411

