You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测自定义键盘悬浮模式?Notification监听未触发问题求助

问题出在哪?

UIResponder.keyboardDidShowNotification是给宿主应用发送的通知,自定义键盘作为独立的App Extension进程,根本收不到宿主的这个通知,所以你加的观察者永远不会被触发。

正确的检测悬浮模式方法

自定义键盘进入悬浮模式时,自身视图的布局会发生明显变化,你可以通过监听视图布局或frame变化来判断:

方案1:重写布局方法

在KeyboardViewController里重写viewWillLayoutSubviews,每次布局时检查键盘视图的frame特征:

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    
    let screenSize = UIScreen.main.bounds.size
    let keyboardFrame = view.frame
    
    // 判断悬浮模式:键盘宽度小于屏幕宽度,或者没有贴紧屏幕底部
    let isFloating = keyboardFrame.width < screenSize.width || 
                     keyboardFrame.maxY < screenSize.height - view.safeAreaInsets.bottom
    
    if isFloating {
        // 这里处理悬浮模式逻辑
        print("键盘进入悬浮模式")
    } else {
        // 正常模式逻辑
        print("键盘处于全屏模式")
    }
}

方案2:用KVO监听frame变化

在viewDidLoad里给键盘视图添加KVO观察者,监听frame变化:

override func viewDidLoad() {
    super.viewDidLoad()
    // 添加frame监听
    view.addObserver(self, forKeyPath: "frame", options: [.new], context: nil)
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    guard keyPath == "frame", let newFrame = change?[.newKey] as? CGRect else {
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        return
    }
    
    let screenSize = UIScreen.main.bounds.size
    let isFloating = newFrame.width < screenSize.width || 
                     newFrame.maxY < screenSize.height - view.safeAreaInsets.bottom
    
    if isFloating {
        // 处理悬浮模式
    }
}

// 记得在销毁时移除观察者
deinit {
    view.removeObserver(self, forKeyPath: "frame")
}
注意点

自定义键盘和宿主App是完全隔离的两个进程,宿主的任何通知、事件都传不到键盘扩展里,所有状态判断都得基于键盘自身的视图变化来做。

内容的提问来源于stack exchange,提问作者Sándor Tatai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 09:43:09