在第一部分中,实现了QQ聊天的界面布局。点击消息发送框,弹出键盘,但是有个缺点是弹出的键盘会将一部分聊天界面遮住。这一部分要实现的功能就是,在弹出键盘时,UITableView
自动上移。在实现这个功能之前时,先了解一下基本的键盘通知和UIDevice通知。
UIDevice
通知
UIDevice
类提供了一个单例对象,它代表着设备,通过它可以获取到一些设备相关的信息,比如电池电量值(batteryLevel)、电池状态(batteryState)、设备类型(model,比如iPod,iPhone等)、系统版本(systemVersion)等等,通过[UIDevice currentDevice]
获取这个对象。
UIDevice
对象会不间断的发出一些通知,下面是其发布通知的名称常量:
UIDeviceOrientationDidChangeNotification // 设备旋转
UIDeviceBatteryStateDidChangeNotification // 电池状态改变
UIDeviceBatteryLevelDidChangeNotification // 电池电量改变
UIDeviceProximityStateDidChangeNotification // 近距离传感器(比如设备贴近了使用者的脸部)
键盘通知
我们经常需要在键盘弹出或者隐藏时做一些特定的操作,因此我们需要监听键盘的状态。键盘状态改变时,系统也会发出一些特定的通知:
UIKeyboardWillShowNotification // 键盘即将显示
UIKeyboardDidShowNotification // 键盘显示完毕
UIKeyboardWillHideNotification // 键盘即将隐藏
UIKeyboardDidHideNotification // 键盘隐藏完毕
UIKeyboardWillChangeFrameNotification // 键盘的位置尺寸即将发生改变
UIKeyboardDidChangeFrameNotification // 键盘的位置尺寸改变完毕
系统发出键盘通知时,会附带以下跟键盘相关的额外信息(字典:userInfo
),字典常见的key如下:
UIKeyboardFrameBeginUserInfoKey // 键盘刚开始的frame
UIKeyboardFrameEndUserInfoKey // 键盘最终的frame(动画执行完毕后)
UIKeyboardAnimationDurationUserInfoKey // 键盘动画的时间
UIKeyboardAnimationCurveUserInfoKey // 键盘动画的执行节奏(快慢)
比如键盘弹出时userInfo
的实例:
userInfo = {
UIKeyboardAnimationCurveUserInfoKey = 7;
UIKeyboardAnimationDurationUserInfoKey = "0.25";
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 796}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 538}";
// 键盘从屏幕最底部弹出{0,667} --> {0,409},键盘高度:258,宽度:375
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
UIKeyboardIsLocalUserInfoKey = 1;
}
键盘隐藏时userInfo
的实例:
userInfo = {
UIKeyboardAnimationCurveUserInfoKey = 7;
UIKeyboardAnimationDurationUserInfoKey = "0.25";
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 538}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 796}";
// 键盘从屏幕滑动到最底部,直到隐藏{0,409} --> {0,667},键盘高度:258,宽度:375
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
UIKeyboardIsLocalUserInfoKey = 1;
}
一个简单示例:当我们在弹出键盘时,为了不让键盘挡住屏幕,会让我们的View向上移动,直到键盘顶部与View底部重合,如下图所示,左边为未弹出键盘时,右边为弹出键盘时:
在整个View加载时,需要监听键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
监听通知的名称UIKeyboardWillShowNotification(键盘即将显示)
和UIKeyboardWillChangeFrameNotification(键盘的位置尺寸即将发生改变)
都可以。如果监听UIKeyboardWillShowNotification
的话,那么你需要同样监听键盘隐藏的通知,然后将View
的位置还原回来。所以我们可以直接监听UIKeyboardWillShowNotification
,然后调整View
的位置。
- (void) keyboardDidChangeFrame:(NSNotification *) notify {
// 从NSNotification获取键盘最终的frame
// 如果是显示键盘,那么就为:{{0, 409}, {375, 258}}
// 如果是隐藏键盘,那么就为:{{0, 667}, {375, 258}}
CGRect distance = [notify.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
// 获取屏幕高度(iPhone6高度:667)
CGFloat screenH = [[UIScreen mainScreen] bounds].size.height;
// 显示键盘:{0,409-667}
// 隐藏键盘:{0,667-667}
self.view.transform = CGAffineTransformMakeTranslation(0, distance.origin.y - screenH);
}