keyboardMan

用法:

keyboardMan_第1张图片

源代码:

import UIKit

final public class KeyboardMan {

var keyboardObserver: NotificationCenter? {

didSet {

oldValue?.removeObserver(self)

keyboardObserver?.addObserver(self, selector: #selector(KeyboardMan.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

keyboardObserver?.addObserver(self, selector: #selector(KeyboardMan.keyboardWillChangeFrame(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)

keyboardObserver?.addObserver(self, selector: #selector(KeyboardMan.keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

keyboardObserver?.addObserver(self, selector: #selector(KeyboardMan.keyboardDidHide(_:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)

}

}

public var keyboardObserveEnabled = false {

willSet {

if newValue != keyboardObserveEnabled {

keyboardObserver = newValue ? NotificationCenter.default : nil

}

}

}

deinit {

// willSet and didSet are not called when deinit, so...

NotificationCenter.default.removeObserver(self)

}

public init() {

}

public struct KeyboardInfo {

public let animationDuration: TimeInterval

public let animationCurve: UInt

public let frameBegin: CGRect

public let frameEnd: CGRect

public var height: CGFloat {

return frameEnd.height

}

public let heightIncrement: CGFloat

public enum Action {

case show

case hide

}

public let action: Action

let isSameAction: Bool

}

public private(set) var appearPostIndex = 0

public private(set) var keyboardInfo: KeyboardInfo? {

willSet {

guard UIApplication.sharedOrNil?.applicationState != .background else {

return

}

guard let info = newValue else {

return

}

if !info.isSameAction || info.heightIncrement != 0 {

// do convenient animation

let duration = info.animationDuration

let curve = info.animationCurve

let options = UIViewAnimationOptions(rawValue: curve << 16 | UIViewAnimationOptions.beginFromCurrentState.rawValue)

UIView.animate(withDuration: duration, delay: 0, options: options, animations: { [weak self] in

guard let strongSelf = self else { return }

switch info.action {

case .show:

strongSelf.animateWhenKeyboardAppear?(strongSelf.appearPostIndex, info.height, info.heightIncrement)

strongSelf.appearPostIndex += 1

case .hide:

strongSelf.animateWhenKeyboardDisappear?(info.height)

strongSelf.appearPostIndex = 0

}

}, completion: nil)

// post full info

postKeyboardInfo?(self, info)

}

}

}

public var animateWhenKeyboardAppear: ((_ appearPostIndex: Int, _ keyboardHeight: CGFloat, _ keyboardHeightIncrement: CGFloat) -> Void)? {

didSet {

keyboardObserveEnabled = true

}

}

public var animateWhenKeyboardDisappear: ((_ keyboardHeight: CGFloat) -> Void)? {

didSet {

keyboardObserveEnabled = true

}

}

public var postKeyboardInfo: ((_ keyboardMan: KeyboardMan, _ keyboardInfo: KeyboardInfo) -> Void)? {

didSet {

keyboardObserveEnabled = true

}

}

// MARK: - Actions

private func handleKeyboard(_ notification: Notification, _ action: KeyboardInfo.Action) {

guard let userInfo = notification.userInfo else {

return

}

let animationDuration: TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue

let animationCurve = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).uintValue

let frameBegin = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue

let frameEnd = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue

let currentHeight = frameEnd.height

let previousHeight = keyboardInfo?.height ?? 0

let heightIncrement = currentHeight - previousHeight

let isSameAction: Bool

if let previousAction = keyboardInfo?.action {

isSameAction = (action == previousAction)

} else {

isSameAction = false

}

keyboardInfo = KeyboardInfo(

animationDuration: animationDuration,

animationCurve: animationCurve,

frameBegin: frameBegin,

frameEnd: frameEnd,

heightIncrement: heightIncrement,

action: action,

isSameAction: isSameAction

)

}

@objc private func keyboardWillShow(_ notification: Notification) {

guard UIApplication.sharedOrNil?.applicationState != .background else {

return

}

handleKeyboard(notification, .show)

}

@objc private func keyboardWillChangeFrame(_ notification: Notification) {

guard UIApplication.sharedOrNil?.applicationState != .background else {

return

}

if let keyboardInfo = keyboardInfo, keyboardInfo.action == .show {

handleKeyboard(notification, .show)

}

}

@objc private func keyboardWillHide(_ notification: Notification) {

guard UIApplication.sharedOrNil?.applicationState != .background else {

return

}

handleKeyboard(notification, .hide)

}

@objc private func keyboardDidHide(_ notification: Notification) {

guard UIApplication.sharedOrNil?.applicationState != .background else {

return

}

keyboardInfo = nil

}

}

extension UIApplication {

// Return UIApplication.shared in an app target, `nil` in an app extension target.

static let sharedOrNil: UIApplication? = {

let selector = NSSelectorFromString("sharedApplication")

guard UIApplication.responds(to: selector) else { return nil }

let application = UIApplication.perform(selector).takeUnretainedValue() as? UIApplication

// The appDelegate is nil, normally it is in app extension context.

guard let _ = application?.delegate else { return nil }

return application

}()

}

你可能感兴趣的:(keyboardMan)