QMUIKeyboardManager

@interface QMUIKeyboardManager : NSObject

QMUIKeyboardManager 提供了方便管理键盘事件的方案,使用的场景是需要跟随键盘的显示或者隐藏来更改界面的 UI,例如输入框跟随在键盘的顶部。 由于键盘通知是整个 App 全局的,所以经常会遇到 A 的键盘监听回调里接收到 B 的键盘事件,这样的情况往往不是我们想要的,即使可以通过判断当前的 firstResponder 来区分,但还是不能完美的解决问题或者有时候解决起来非常麻烦。QMUIKeyboardManager 通过 delegateEnabledtargetResponder 等属性来方便地控制 firstResponder,从而可以实现某个键盘监听回调方法只响应某个 UIResponder 或者某几个 UIResponder 触发的键盘通知。 使用方式:

  1. 使用 initWithDelegate: 方法初始化
  2. 通过 addTargetResponder: 的方式将要监听的输入框添加进来
  3. 在 delegate 方法里(一般用 keyboardWillChangeFrameWithUserInfo:)处理键盘位置变化时的布局

另外 QMUIKeyboardManager 同时集成在了 UITextField(QMUI) 和 UITextView(QMUI) 里,具体请查看对应文件。

See

UITextField(QMUI)

See

UITextView(QMUI)
  • 指定初始化方法,以 delegate 的方式将键盘事件传递给监听者

    Declaration

    Objective-C

    - (instancetype)initWithDelegate:(id<QMUIKeyboardManagerDelegate>)delegate;

    Swift

    init!(delegate: QMUIKeyboardManagerDelegate!)
  • 获取当前的 delegate

    Declaration

    Objective-C

    @property (nonatomic, weak, readonly) id<QMUIKeyboardManagerDelegate> delegate;

    Swift

    weak var delegate: QMUIKeyboardManagerDelegate! { get }
  • 是否允许触发delegate的回调,常见的场景例如在 UIViewController viewWillAppear: 里打开,在 viewWillDisappear: 里关闭,从而避免在键盘升起的状态下手势返回时界面布局会跟着键盘往下移动。 默认为 YES。

    Declaration

    Objective-C

    @property (nonatomic) BOOL delegateEnabled;

    Swift

    var delegateEnabled: Bool { get set }
  • 是否忽视 applicationState 状态的影响。默认为 NO,也即只有 UIApplicationStateActive 才会响应通知,如果设置为 YES,则任何 state 都会响应通知。

    Declaration

    Objective-C

    @property (nonatomic) BOOL ignoreApplicationState;

    Swift

    var ignoreApplicationState: Bool { get set }
  • 添加触发键盘事件的 UIResponder,一般是 UITextView 或者 UITextField ,不添加 targetResponder 的话,则默认接受任何 UIResponder 产生的键盘通知。 添加成功将会返回YES,否则返回NO。

    Declaration

    Objective-C

    - (BOOL)addTargetResponder:(UIResponder *)targetResponder;

    Swift

    func addTargetResponder(_ targetResponder: UIResponder!) -> Bool
  • 获取当前所有的 target UIResponder,若不存在则返回 nil

    Declaration

    Objective-C

    - (NSArray<UIResponder *> *)allTargetResponders;

    Swift

    func allTargetResponders() -> [UIResponder]!
  • 移除 targetResponder 跟 keyboardManager 的关系,如果成功会返回 YES

    Declaration

    Objective-C

    - (BOOL)removeTargetResponder:(UIResponder *)targetResponder;

    Swift

    func removeTargetResponder(_ targetResponder: UIResponder!) -> Bool
  • 把键盘的rect转为相对于view的rect。一般用来把键盘的rect转化为相对于当前 self.view 的 rect,然后获取 y 值来布局对应的 view(这里一般不要获取键盘的高度,因为对于iPad的键盘,浮动状态下键盘的高度往往不是我们想要的)。

    Declaration

    Objective-C

    + (CGRect)convertKeyboardRect:(CGRect)rect toView:(UIView *)view;

    Swift

    class func convertKeyboardRect(_ rect: CGRect, to view: UIView!) -> CGRect

    Parameters

    rect

    键盘的rect,一般拿 keyboardUserInfo.endFrame

    view

    一个特定的view或者window,如果传入nil则相对有当前的 mainWindow

  • 获取键盘到顶部到相对于view底部的距离,这个值在某些情况下会等于endFrame.size.height或者visibleKeyboardHeight,不过在iPad浮动键盘的时候就包括了底部的空隙。所以建议使用这个方法。

    Declaration

    Objective-C

    + (CGFloat)distanceFromMinYToBottomInView:(UIView *)view
                                 keyboardRect:(CGRect)rect;

    Swift

    class func distanceFromMinYToBottom(in view: UIView!, keyboardRect rect: CGRect) -> CGFloat
  • 根据键盘的动画参数自己构建一个动画,调用者只需要设置view的位置即可

    Declaration

    Objective-C

    + (void)animateWithAnimated:(BOOL)animated
               keyboardUserInfo:(QMUIKeyboardUserInfo *)keyboardUserInfo
                     animations:(void (^)(void))animations
                     completion:(void (^)(BOOL))completion;

    Swift

    class func animateWith(animated: Bool, keyboardUserInfo: QMUIKeyboardUserInfo!, animations: (() -> Void)!, completion: ((Bool) -> Void)!)
  • 这个方法特殊处理 iPad Pro 外接键盘的情况。使用外接键盘在完全不显示键盘的时候,不会调用willShow的通知,所以导致一些通过willShow回调来显示targetResponder的场景(例如微信朋友圈的评论输入框)无法把targetResponder正常的显示出来。通过这个方法,你只需要关心你的show和hide的状态就好了,不需要关心是否 iPad Pro 的情况。

    Declaration

    Objective-C

    + (void)
        handleKeyboardNotificationWithUserInfo:
            (QMUIKeyboardUserInfo *)keyboardUserInfo
                                     showBlock:
                                         (void (^)(QMUIKeyboardUserInfo *))showBlock
                                     hideBlock:(void (^)(QMUIKeyboardUserInfo *))
                                                   hideBlock;

    Swift

    class func handleKeyboardNotification(with keyboardUserInfo: QMUIKeyboardUserInfo!, show showBlock: ((QMUIKeyboardUserInfo?) -> Void)!, hide hideBlock: ((QMUIKeyboardUserInfo?) -> Void)!)

    Parameters

    showBlock

    键盘显示回调的block,不能把showBlock理解为系统的show通知,而是你有输入框聚焦了并且期望键盘显示出来。

    hideBlock

    键盘隐藏回调的block,不能把hideBlock理解为系统的hide通知,而是键盘即将消失在界面上并且你期望跟随键盘变化的UI回到默认状态。

  • 键盘面板的私有view,可能为nil

    Declaration

    Objective-C

    + (UIView *)keyboardView;

    Swift

    class func keyboardView() -> UIView!
  • 键盘面板所在的私有window,可能为nil

    Declaration

    Objective-C

    + (UIWindow *)keyboardWindow;

    Swift

    class func keyboardWindow() -> UIWindow!
  • 是否有键盘在显示

    Declaration

    Objective-C

    + (BOOL)isKeyboardVisible;

    Swift

    class func isKeyboardVisible() -> Bool
  • 当期那键盘相对于屏幕的frame

    Declaration

    Objective-C

    + (CGRect)currentKeyboardFrame;

    Swift

    class func currentKeyboardFrame() -> CGRect
  • 当前键盘高度键盘的可见高度

    Declaration

    Objective-C

    + (CGFloat)visibleKeyboardHeight;

    Swift

    class func visibleKeyboardHeight() -> CGFloat