首页 文章

从Swift中的userInfo获取键盘大小

提问于
浏览
76

我一直在尝试添加一些代码来在键盘出现时移动我的视图,但是,我在尝试将Objective-C示例转换为Swift时遇到了问题 . 我已经取得了一些进展,但我被困在一条特定的路线上 .

这些是我一直关注的两个教程/问题:

How to move content of UIViewController upwards as Keypad appears using Swift http://www.ioscreator.com/tutorials/move-view-when-keyboard-appears

这是我目前的代码:

override func viewWillAppear(animated: Bool) {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}

override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
    var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
    UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
    let frame = self.budgetEntryView.frame
    frame.origin.y = frame.origin.y - keyboardSize
    self.budgetEntryView.frame = frame
}

func keyboardWillHide(notification: NSNotification) {
    //
}

目前,我在这一行收到错误:

var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))

如果有人能让我知道这行代码应该是什么,我应该设法自己弄清楚其余部分 .

10 回答

  • 1

    这对我有帮助:https://developer.apple.com/library/ios/samplecode/UICatalog/Listings/Swift_UICatalog_TextViewController_swift.html

    let userInfo = notification.userInfo!
    
    let animationDuration: NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as NSNumber).doubleValue
    let keyboardScreenBeginFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as NSValue).CGRectValue()
    let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as NSValue).CGRectValue()
    
  • 10

    您的 生产环境 线存在一些问题

    var keyboardSize = notification.userInfo(valueForKey(UIKeyboardFrameBeginUserInfoKey))
    
    • notification.userInfo 返回一个可选字典 [NSObject : AnyObject]? ,因此必须在访问其值之前将其解包 .

    • Objective-C NSDictionary 映射到Swift本机字典,因此必须使用字典下标语法( dict[key] )来访问值 .

    • 必须将值强制转换为 NSValue ,以便可以在其上调用 CGRectValue .

    所有这些都可以通过可选赋值,可选链接和可选转换的组合来实现:

    if let userInfo = notification.userInfo {
       if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
           // ...
       } else {
           // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
       }
    } else {
       // no userInfo dictionary in notification
    }
    

    或者一步到位:

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
        // ...
    }
    

    Update for Swift 3.0.1 (Xcode 8.1):

    if let userInfo = notification.userInfo {
        if let keyboardSize = userInfo[UIKeyboardFrameBeginUserInfoKey] as? CGRect {
            let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
            // ...
        } else {
            // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
        }
    } else {
        // no userInfo dictionary in notification
    }
    

    或者一步到位:

    if let keyboardSize = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? CGRect {
        let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
        // ...
    }
    
  • 17

    对于更少的代码,请考虑查看THIS

    这对我真的很有帮助 . 您只需在视图控制器中包含视图约束并使用您添加的两个观察者 . 然后只需使用以下方法(这里假设你移动一个tableView)

    func keyboardWillShow(sender: NSNotification) {
            if let userInfo = sender.userInfo {
                if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size.height {
                    tableViewBottomConstraint.constant = keyboardHeight
                    UIView.animateWithDuration(0.25, animations: { () -> Void in
                        self.view.layoutIfNeeded()
                    })
                }
            }
        }
    

    func keyboardWillHide(sender: NSNotification) {
    if let userInfo = sender.userInfo {
      if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size.height {
        tableViewBottomConstraint.constant = 0.0
        UIView.animateWithDuration(0.25, animations: { () -> Void in self.view.layoutIfNeeded() })
      }
    } }
    
  • 180

    如果您使用的是故事板,而不是操纵视图本身,则可以利用自动布局 .

    (这是尼古拉斯答案的清理版)

    设置通知中心以通知您键盘的外观和消失:

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
    
    }
    

    并确保在不再需要时删除观察者:

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
    }
    

    在故事板内部,设置底部约束 . 创建该约束的出口:

    enter image description here

    并在显示或隐藏键盘时设置约束的常量属性:

    func keyboardWillShow(notification: NSNotification) {
        guard let keyboardHeight = (notification.userInfo! as NSDictionary).objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue.size.height else {
            return
        }
        nameOfOutlet.constant = keyboardHeight
        view.layoutIfNeeded()
    }
    
    func keyboardWillHide(notification: NSNotification) {
        nameOfOutlet.constant = 0.0
        view.layoutIfNeeded()
    }
    

    现在,只要键盘出现或消失,自动布局就会照顾好一切 .

  • 0

    Swift 2

    func keyboardWasShown(notification:NSNotification) {
            guard let info:[NSObject:AnyObject] = notification.userInfo,
                let keyboardSize:CGSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size else { return }
    
            let insets:UIEdgeInsets = UIEdgeInsetsMake(self.scrollView.contentInset.top, 0.0, keyboardSize.height, 0.0)
    
            self.scrollView.contentInset = insets
            self.scrollView.scrollIndicatorInsets = insets
        }
    

    Swift 3

    func keyboardWasShown(notification:NSNotification) {
        guard let info:[AnyHashable:Any] = notification.userInfo,
            let keyboardSize:CGSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size else { return }
    
        let insets:UIEdgeInsets = UIEdgeInsets(top: self.scrollView.contentInset.top, left: 0.0, bottom: keyboardSize.height, right: 0.0)
    
        self.scrollView.contentInset = insets
        self.scrollView.scrollIndicatorInsets = insets
    }
    
  • 3

    您可以将这一行用于您的 生产环境 线

    var keyboardSize:CGSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue().size
    
  • 0

    Swift 3: UPDATE

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
    }
    
  • 0

    Swift 3.0

    这是一个检索键盘大小并使用它来向上动画视图的示例 . 在我的情况下,当用户开始输入时,我正在向上移动包含我的UITextFields的UIView,这样他们就可以完成一个表单并仍然可以看到底部的提交按钮 .

    我添加了一个出口到我想要动画的视图的底部空间约束,并将其命名为 myViewsBottomSpaceConstraint

    @IBOutlet weak var myViewsBottomSpaceConstraint: NSLayoutConstraint!
    

    然后我将以下代码添加到我的swift类中:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
    }
    
    func keyboardWillShow(notification: NSNotification) {
    
        let userInfo = notification.userInfo as! [String: NSObject] as NSDictionary
        let keyboardFrame = userInfo.value(forKey: UIKeyboardFrameEndUserInfoKey) as! CGRect
        let keyboardHeight = keyboardFrame.height
        myViewsBottomSpaceConstraint.constant = keyboardHeight
        view.layoutIfNeeded()
    }
    
    func keyboardWillHide(notification: NSNotification) {
        myViewsBottomSpaceConstraint.constant = 0.0
        view.layoutIfNeeded()
    }
    
  • 3

    详情

    xCode 8.2.1,swift 3

    代码

    KeyboardNotifications

    import Foundation
    
    class KeyboardNotifications {
    
        fileprivate var _isEnabled: Bool
        fileprivate var notifications:  [KeyboardNotificationsType]
        fileprivate var delegate: KeyboardNotificationsDelegate
    
        init(notifications: [KeyboardNotificationsType], delegate: KeyboardNotificationsDelegate) {
            _isEnabled = false
            self.notifications = notifications
            self.delegate = delegate
        }
    
        deinit {
            if isEnabled {
                isEnabled = false
            }
        }
    }
    
    // MARK: - enums
    
    extension KeyboardNotifications {
    
        enum KeyboardNotificationsType {
            case willShow, willHide, didShow, didHide
    
            var selector: Selector {
                switch self {
    
                case .willShow:
                    return #selector(KeyboardNotifications.keyboardWillShow(notification:))
    
                case .willHide:
                    return #selector(KeyboardNotifications.keyboardWillHide(notification:))
    
                case .didShow:
                    return #selector(KeyboardNotifications.keyboardDidShow(notification:))
    
                case .didHide:
                    return #selector(KeyboardNotifications.keyboardDidHide(notification:))
    
                }
            }
    
            var notificationName: NSNotification.Name {
                switch self {
    
                case .willShow:
                    return .UIKeyboardWillShow
    
                case .willHide:
                    return .UIKeyboardWillHide
    
                case .didShow:
                    return .UIKeyboardDidShow
    
                case .didHide:
                    return .UIKeyboardDidHide
                }
            }
        }
    }
    
    // MARK: - isEnabled
    
    extension KeyboardNotifications {
    
        private func addObserver(type: KeyboardNotificationsType) {
            NotificationCenter.default.addObserver(self, selector: type.selector, name: type.notificationName, object: nil)
            print("\(type.notificationName.rawValue) inited")
        }
    
        var isEnabled: Bool {
            set {
                if newValue {
    
                    for notificaton in notifications {
                        addObserver(type: notificaton)
                    }
                } else {
                    NotificationCenter.default.removeObserver(self)
                    print("Keyboard notifications deinited")
                }
                _isEnabled = newValue
            }
    
            get {
                return _isEnabled
            }
        }
    
    }
    
    // MARK: - Notification functions
    
    extension KeyboardNotifications {
    
        @objc
        func keyboardWillShow(notification: NSNotification) {
            delegate.keyboardWillShow?(notification: notification)
        }
    
        @objc
        func keyboardWillHide(notification: NSNotification) {
            delegate.keyboardWillHide?(notification: notification)
        }
    
        @objc
        func keyboardDidShow(notification: NSNotification) {
            delegate.keyboardDidShow?(notification: notification)
        }
    
        @objc
        func keyboardDidHide(notification: NSNotification) {
            delegate.keyboardDidHide?(notification: notification)
        }
    }
    

    KeyboardNotificationsDelegate

    import Foundation
    
    @objc
    protocol KeyboardNotificationsDelegate {
    
        @objc optional func keyboardWillShow(notification: NSNotification)
        @objc optional func keyboardWillHide(notification: NSNotification)
        @objc optional func keyboardDidShow(notification: NSNotification)
        @objc optional func keyboardDidHide(notification: NSNotification)
    }
    

    用法

    class ViewController: UIViewController {
          private var keyboardNotifications: KeyboardNotifications!
          override func viewDidLoad() {
               super.viewDidLoad()
               ...
                keyboardNotifications = KeyboardNotifications(notifications: [.willShow, .willHide, .didShow, .didHide], delegate: self)
          }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            keyboardNotifications.isEnabled = true
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            keyboardNotifications.isEnabled = false
        }
    
     }
    
     extension ViewController: KeyboardNotificationsDelegate {
    
        // If you don't need this func you can remove it
        func keyboardWillShow(notification: NSNotification) {
               ...
        }
    
        // If you don't need this func you can remove it
        func keyboardWillHide(notification: NSNotification) {
               ...
        }
    
        // If you don't need this func you can remove it
        func keyboardDidShow(notification: NSNotification) {
               ...
        }
    
        // If you don't need this func you can remove it
        func keyboardDidHide(notification: NSNotification) {
               ...
        }
    }
    

    完整样本

    import UIKit
    
    class ViewController: UIViewController {
    
        private var keyboardNotifications: KeyboardNotifications!
        private var textField = UITextField(frame: CGRect(x: 40, y: 40, width: 200, height: 30))
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            view.addSubview(textField)
    
            // when you will tap on view (background) the keyboard will hide
            // read about view.disableKeybordWhenTapped here: http://stackoverflow.com/a/42187286/4488252
            view.disableKeybordWhenTapped = true
    
            keyboardNotifications = KeyboardNotifications(notifications: [.willShow, .willHide, .didShow, .didHide], delegate: self)
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            keyboardNotifications.isEnabled = true
        }
    
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            keyboardNotifications.isEnabled = false
        }
    
    }
    
     extension ViewController: KeyboardNotificationsDelegate {
    
        // If you don't need this func you can remove it
        func keyboardWillShow(notification: NSNotification) {
            print("keyboardWillShow")
            let userInfo = notification.userInfo as! [String: NSObject]
            let keyboardFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as! CGRect
            print("keyboardFrame: \(keyboardFrame)")
        }
    
        // If you don't need this func you can remove it
        func keyboardWillHide(notification: NSNotification) {
            print("keyboardWillHide")
        }
    
        // If you don't need this func you can remove it
        func keyboardDidShow(notification: NSNotification) {
            print("keyboardDidShow")
        }
    
        // If you don't need this func you can remove it
        func keyboardDidHide(notification: NSNotification) {
     print("keyboardDidHide")
        }
    }
    

    结果

    enter image description here

    日志

    enter image description here

  • 1

    对于xamarin,您可以使用c#6

    private void KeyboardWillChangeFrame(NSNotification notification)
    {
            var keyboardSize = notification.UserInfo.ValueForKey(UIKeyboard.FrameEndUserInfoKey) as NSValue;
            if (keyboardSize != null)
            {
                var rect= keyboardSize.CGRectValue;
                //do your stuff here
            }
    }
    

    C#7

    private void KeyboardWillChangeFrame(NSNotification notification)
       {
           if (!(notification.UserInfo.ValueForKey(UIKeyboard.FrameEndUserInfoKey) is NSValue keyboardSize)) return;
           var rect= keyboardSize.CGRectValue;
       }
    

相关问题