簡體   English   中英

在iOS8中無法獲得正確的鍵盤高度值

[英]can't get correct value of keyboard height in iOS8

我使用此代碼來確定鍵盤的大小:

- (void)keyboardWillChange:(NSNotification *)notification {
    NSDictionary* keyboardInfo = [notification userInfo];
    NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
    CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];

}

我在模擬器中運行它。

問題是因為iOS 8這將不會給出正確的值,如果鍵盤建議已啟動或者如果我將它們向下推,則會得到不同的(不正確的)值。

如何獲得鍵盤的確切大小,包括鍵盤建議?

隨着iOS中自定義鍵盤的引入,這個問題變得更加復雜。

簡而言之, UIKeyboardWillShowNotification可以通過自定義鍵盤實現多次調用:

  1. 打開Apple系統鍵盤時(縱向)
    • 發送UIKeyboardWillShowNotification時鍵盤高度為224
  2. 打開Swype鍵盤時 (縱向):
    • 發送UIKeyboardWillShowNotification時鍵盤高度為0
    • 發送UIKeyboardWillShowNotification時鍵盤高度為216
    • 發送UIKeyboardWillShowNotification時鍵盤高度為256
  3. 打開SwiftKey鍵盤時 (縱向):
    • 發送UIKeyboardWillShowNotification時鍵盤高度為0
    • 發送UIKeyboardWillShowNotification時鍵盤高度為216
    • 發送UIKeyboardWillShowNotification時鍵盤高度為259

為了在一個代碼行中正確處理這些場景,您需要:

注冊針對UIKeyboardWillShowNotificationUIKeyboardWillHideNotification通知的觀察者:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];    
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide:)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];

創建一個全局變量來跟蹤當前鍵盤高度:

CGFloat _currentKeyboardHeight = 0.0f;

實現keyboardWillShow以響應鍵盤高度的當前變化:

- (void)keyboardWillShow:(NSNotification*)notification {
   NSDictionary *info = [notification userInfo];
   CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
   CGFloat deltaHeight = kbSize.height - _currentKeyboardHeight; 
   // Write code to adjust views accordingly using deltaHeight
   _currentKeyboardHeight = kbSize.height;
}

注意:您可能希望為視圖的偏移設置動畫。 信息字典包含由UIKeyboardAnimationDurationUserInfoKey鍵入的值。 此值可用於以與顯示的鍵盤相同的速度為更改設置動畫。

keyboardWillHide實現為reset _currentKeyboardHeight並對被解除的鍵盤作出反應:

- (void)keyboardWillHide:(NSNotification*)notification {
   NSDictionary *info = [notification userInfo];
   CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
   // Write code to adjust views accordingly using kbSize.height
   _currentKeyboardHeight = 0.0f;
}

使用

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

我也有這個問題,直到我遇到這篇StackOverflow文章:

轉換UIKeyboardFrameEndUserInfoKey

這將向您展示如何使用convertRect函數,將鍵盤的大小轉換為可用的,但在屏幕方向上。

NSDictionary* d = [notification userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [myView convertRect:r fromView:nil];

以前,我有一個iPad應用程序使用UIKeyboardFrameEndUserInfoKey沒有使用convertRect ,它工作正常。

但是對於iOS 8,它已經不再適用了。 突然間,它會報告我在橫向模式下在iPad上運行的鍵盤高度1024像素

現在,對於iOS 8,您必須使用此convertRect功能。

類似於用Swift 2.0編寫的dgangsta解決方案:

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

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
    guard let kbSizeValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
    guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return }
    animateToKeyboardHeight(kbSizeValue.CGRectValue().height, duration: kbDurationNumber.doubleValue)
}

func keyboardWillHide(notification: NSNotification) {
    guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return }
    animateToKeyboardHeight(0, duration: kbDurationNumber.doubleValue)
}

func animateToKeyboardHeight(kbHeight: CGFloat, duration: Double) {
    // your custom code here
}

我為UIViewController做了extension

extension UIViewController {
    func keyboardWillChangeFrameNotification(notification: NSNotification, scrollBottomConstant: NSLayoutConstraint) {
        let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
        let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
        let keyboardBeginFrame = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
        let keyboardEndFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()

        let screenHeight = UIScreen.mainScreen().bounds.height
        let isBeginOrEnd = keyboardBeginFrame.origin.y == screenHeight || keyboardEndFrame.origin.y == screenHeight
        let heightOffset = keyboardBeginFrame.origin.y - keyboardEndFrame.origin.y - (isBeginOrEnd ? bottomLayoutGuide.length : 0)

        UIView.animateWithDuration(duration.doubleValue,
            delay: 0,
            options: UIViewAnimationOptions(rawValue: UInt(curve.integerValue << 16)),
            animations: { () in
                scrollBottomConstant.constant = scrollBottomConstant.constant + heightOffset
                self.view.layoutIfNeeded()
            },
            completion: nil
        )
    }
}

你可以像這樣使用:

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChangeFrameNotification:", name: UIKeyboardWillChangeFrameNotification, object: nil)
}

...

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillChangeFrameNotification(notification: NSNotification) {
    self.keyboardWillChangeFrameNotification(notification, scrollBottomConstant: inputContainerBottom)
    // Write more to here if you want.
}

有些時候開發人員在實際顯示之前需要知道鍵盤高度,允許他們適當地預先布局界面。

如果是這種情況,這里是一個包容性規范:

在此輸入圖像描述

這包括頂部的快速類型欄,因為在所有當前版本的iOS中默認啟用它。

以下是我用來測試這個的swift 3通知設置,如果有人需要它:

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
}

func keyboardWillShow(notification: NSNotification) {
    guard let keyboardSize = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
    print("\(keyboardSize)")
}

我注意到在默認鍵盤和自定義( UIPickerView )鍵盤之間切換時出現問題 - 從默認鍵盤切換后,自定義鍵盤將顯示253高度而不是162。

在這種情況下有效的是設置autocorrectionType = UITextAutocorrectionTypeNo; 用於具有自定義鍵盤的輸入字段。

該問題僅發生在iOS 8中(僅在模擬器上測試)。 它不會出現在iOS 9(模擬器或設備)中。

swift只有一個字符串:

let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size

UIKeyboardFrameEndUserInfoKey始終存儲NSValue ,因此無需檢查它。

在Swift中,不是一行......

self.keyboardDidShowObserver = NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { (notification) in
        if let userInfo = notification.userInfo, let keyboardFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue {
            let keyboardRect = keyboardFrameValue.CGRectValue()
            // keyboardRect.height gives the height of the keyboard
            // your additional code here...
        }
    })
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {

    float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

}];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM