在涉及到表單輸入的界面中,我們通常需要監聽一些鍵盤事件,並根據實際需要來執行相應的操作。如,鍵盤彈起時,要讓我們的UIScrollView自動收縮,以能看到整個UIScrollView的內容。為此,在UIWindow.h中定義了如下6個通知常量,來配合鍵盤在不同時間點的事件處理:
UIKeyboardWillShowNotification // 鍵盤顯示之前 UIKeyboardDidShowNotification // 鍵盤顯示完成後 UIKeyboardWillHideNotification // 鍵盤隱藏之前 UIKeyboardDidHideNotification // 鍵盤消息之後 UIKeyboardWillChangeFrameNotification // 鍵盤大小改變之前 UIKeyboardDidChangeFrameNotification // 鍵盤大小改變之後
這幾個通知的object對象都是nil。而userInfo字典都包含了一些鍵盤的信息,主要是鍵盤的位置大小信息,我們可以通過使用以下的key來獲取字典中對應的值:
// 鍵盤在動畫開始前的frame let UIKeyboardFrameBeginUserInfoKey: String // 鍵盤在動畫線束後的frame let UIKeyboardFrameEndUserInfoKey: String // 鍵盤的動畫曲線 let UIKeyboardAnimationCurveUserInfoKey: String // 鍵盤的動畫時間 let UIKeyboardAnimationDurationUserInfoKey: String
在此,我感興趣的是鍵盤事件的調用順序和如何獲取鍵盤的大小,以適當的調整視圖的大小。
從定義的鍵盤通知的類型可以看到,實際上我們關注的是三個階段的鍵盤的事件:顯示、隱藏、大小改變。在此我們設定兩個UITextField,它們的鍵盤類型不同:一個是普通鍵盤,一個是數字鍵盤。我們監聽所有的鍵盤事件,並打印相關日志(在此就不貼代碼了),直接看結果。
1) 當我們讓textField1獲取輸入焦點時,打印的日志如下:
keyboard will change keyboard will show keyboard did change keyboard did show
2) 在不隱藏鍵盤的情況下,讓textField2獲取焦點,打印的日志如下:
keyboard will change keyboard will show keyboard did change keyboard did show
3) 再收起鍵盤,打印的日志如下:
keyboard will change keyboard will hide keyboard did change keyboard did hide
從上面的日志可以看出,不管是鍵盤的顯示還是隱藏,都會發送大小改變的通知,而且是在show和hide的對應事件之前。而在大小不同的鍵盤之間切換時,除了發送change事件外,還會發送show事件(不發送hide事件)。
另外還有兩點需要注意的是:
如果是在兩個大小相同的鍵盤之間切換,則不會發送任何消息
如果是普通鍵盤中類似於中英文鍵盤的切換,只要大小改變了,都會發送一組或多組與上面2)相同流程的消息
了解了事件的調用順序,我們就可以根據自己的需要來決定在哪個消息處理方法中來執行操作。為此,我們需要獲取一些有用的信息。這些信息是封裝在通知的userInfo中,通過上面常量key來獲取相關的值。通常我們關心的是UIKeyboardFrameEndUserInfoKey,來獲取動畫完成後,鍵盤的frame,以此來計算我們的scroll view的高度。另外,我們可能希望scroll view高度的變化也是通過動畫來過渡的,此時UIKeyboardAnimationCurveUserInfoKey和UIKeyboardAnimationDurationUserInfoKey就有用了。
我們可以通過以下方式來獲取這些值:
if let dict = notification.userInfo { var animationDuration: NSTimeInterval = 0 var animationCurve: UIViewAnimationCurve = .EaseInOut var keyboardEndFrame: CGRect = CGRectZero dict[UIKeyboardAnimationCurveUserInfoKey]?.getValue(&animationCurve) dict[UIKeyboardAnimationDurationUserInfoKey]?.getValue(&animationDuration) dict[UIKeyboardFrameEndUserInfoKey]?.getValue(&keyboardEndFrame) ...... }
實際上,userInfo中還有另外三個值,只不過這幾個值從iOS 3.2開始就已經廢棄不用了。所以我們不用太關注。
最後說下表單。一個表單界面看著比較簡單,但交互和UI總是能想出各種方法來讓它變得復雜,而且其實裡面設計到的細節還是很多的。像我們金融類的App,通常都會涉及到大量的表單輸入,所以如何做好,還是需要花一番心思的。空閒時,打算總結一下,寫一篇文章。
參考
UIWindow Class Reference