iOS 键盘事件

在涉及到表单输入的界面中,我们通常需要监听一些键盘事件,并根据实际需要来执行相应的操作。如,键盘弹起时,要让我们的UIScrollView自动收缩,以能看到整个UIScrollView的内容。为此,在UIWindow.h中定义了如下6个通知常量,来配合键盘在不同时间点的事件处理:

1
2
3
4
5
6
UIKeyboardWillShowNotification			// 键盘显示之前
UIKeyboardDidShowNotification // 键盘显示完成后
UIKeyboardWillHideNotification // 键盘隐藏之前
UIKeyboardDidHideNotification // 键盘消息之后
UIKeyboardWillChangeFrameNotification // 键盘大小改变之前
UIKeyboardDidChangeFrameNotification // 键盘大小改变之后

这几个通知的object对象都是nil。而userInfo字典都包含了一些键盘的信息,主要是键盘的位置大小信息,我们可以通过使用以下的key来获取字典中对应的值:

1
2
3
4
5
6
7
8
9
10
11
// 键盘在动画开始前的frame
let UIKeyboardFrameBeginUserInfoKey: String

// 键盘在动画线束后的frame
let UIKeyboardFrameEndUserInfoKey: String

// 键盘的动画曲线
let UIKeyboardAnimationCurveUserInfoKey: String

// 键盘的动画时间
let UIKeyboardAnimationDurationUserInfoKey: String

在此,我感兴趣的是键盘事件的调用顺序和如何获取键盘的大小,以适当的调整视图的大小。

从定义的键盘通知的类型可以看到,实际上我们关注的是三个阶段的键盘的事件:显示、隐藏、大小改变。在此我们设定两个UITextField,它们的键盘类型不同:一个是普通键盘,一个是数字键盘。我们监听所有的键盘事件,并打印相关日志(在此就不贴代码了),直接看结果。

1) 当我们让textField1获取输入焦点时,打印的日志如下:

1
2
3
4
keyboard will change
keyboard will show
keyboard did change
keyboard did show

2) 在不隐藏键盘的情况下,让textField2获取焦点,打印的日志如下:

1
2
3
4
keyboard will change
keyboard will show
keyboard did change
keyboard did show

3) 再收起键盘,打印的日志如下:

1
2
3
4
keyboard will change
keyboard will hide
keyboard did change
keyboard did hide

从上面的日志可以看出,不管是键盘的显示还是隐藏,都会发送大小改变的通知,而且是在showhide的对应事件之前。而在大小不同的键盘之间切换时,除了发送change事件外,还会发送show事件(不发送hide事件)。

另外还有两点需要注意的是:

  1. 如果是在两个大小相同的键盘之间切换,则不会发送任何消息
  2. 如果是普通键盘中类似于中英文键盘的切换,只要大小改变了,都会发送一组或多组与上面2)相同流程的消息

了解了事件的调用顺序,我们就可以根据自己的需要来决定在哪个消息处理方法中来执行操作。为此,我们需要获取一些有用的信息。这些信息是封装在通知的userInfo中,通过上面常量key来获取相关的值。通常我们关心的是UIKeyboardFrameEndUserInfoKey,来获取动画完成后,键盘的frame,以此来计算我们的scroll view的高度。另外,我们可能希望scroll view高度的变化也是通过动画来过渡的,此时UIKeyboardAnimationCurveUserInfoKeyUIKeyboardAnimationDurationUserInfoKey就有用了。

我们可以通过以下方式来获取这些值:

1
2
3
4
5
6
7
8
9
10
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)
......
}
招摇撞骗