iOS - 键盘通知(NSNotificationCenter)
2017-11-14 本文已影响231人
SkyMing一C
图片源于网络
键盘通知的基本信息
当键盘弹出时,键盘高度会随着键盘语言变化(中文要高些),在这种情况下一般而言对于界面需要重新布局。这就需要用到键盘通知(NSNotificationCenter)。
- 键盘通知目前的SDK里总共有如下6个:
UIKIT_EXTERN NSNotificationName const UIKeyboardWillShowNotification __TVOS_PROHIBITED;
UIKIT_EXTERN NSNotificationName const UIKeyboardDidShowNotification __TVOS_PROHIBITED;
UIKIT_EXTERN NSNotificationName const UIKeyboardWillHideNotification __TVOS_PROHIBITED;
UIKIT_EXTERN NSNotificationName const UIKeyboardDidHideNotification __TVOS_PROHIBITED;
// Like the standard keyboard notifications above, these additional notifications include
// a nil object and begin/end frames of the keyboard in screen coordinates in the userInfo dictionary.
UIKIT_EXTERN NSNotificationName const UIKeyboardWillChangeFrameNotification NS_AVAILABLE_IOS(5_0) __TVOS_PROHIBITED;
UIKIT_EXTERN NSNotificationName const UIKeyboardDidChangeFrameNotification NS_AVAILABLE_IOS(5_0) __TVOS_PROHIBITED;
通知是一种消息机制,addObserver与removeObserver需要在对应的生命周期中成对出现。
在键盘通知(NSNotificationCenter)的userInfo字典中包含了一些键盘frame以及动画相关的信息:
UIKIT_EXTERN NSString *const UIKeyboardFrameBeginUserInfoKey NS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED; // NSValue of CGRect
UIKIT_EXTERN NSString *const UIKeyboardFrameEndUserInfoKey NS_AVAILABLE_IOS(3_2) __TVOS_PROHIBITED; // NSValue of CGRect
UIKIT_EXTERN NSString *const UIKeyboardAnimationDurationUserInfoKey NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED; // NSNumber of double
UIKIT_EXTERN NSString *const UIKeyboardAnimationCurveUserInfoKey NS_AVAILABLE_IOS(3_0) __TVOS_PROHIBITED; // NSNumber of NSUInteger (UIViewAnimationCurve)
UIKIT_EXTERN NSString *const UIKeyboardIsLocalUserInfoKey NS_AVAILABLE_IOS(9_0) __TVOS_PROHIBITED; // NSNumber of BOOL
// These keys are superseded by UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey.
UIKIT_EXTERN NSString *const UIKeyboardCenterBeginUserInfoKey NS_DEPRECATED_IOS(2_0, 3_2) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIKeyboardCenterEndUserInfoKey NS_DEPRECATED_IOS(2_0, 3_2) __TVOS_PROHIBITED;
UIKIT_EXTERN NSString *const UIKeyboardBoundsUserInfoKey NS_DEPRECATED_IOS(2_0, 3_2) __TVOS_PROHIBITED;
- NSValue: NSValue提供了简单的容器来包含C或Objective-C数据项。可以容纳任何基本数据类型如char,int,float,double,以及指针,结构体和对象ids。NSArray和NSSet集合类对象要求它们的元素为对象类型,NSValue的主要目的是使这些数据类型可以添加至集合中。NSValue对象是不可变类型。 简而言之,NSValue是基本数据类型或自定义数据类型所定义变量的对象包装器。
注:NSNumber等都是继承于NSValue。(通过NSValueUIGeometryExtensions这个类别封装CGPoint,CGSize,CGRect等结构体)
@interface NSValue (NSValueUIGeometryExtensions)
+ (NSValue *)valueWithCGPoint:(CGPoint)point;
+ (NSValue *)valueWithCGSize:(CGSize)size;
+ (NSValue *)valueWithCGRect:(CGRect)rect;
+ (NSValue *)valueWithCGAffineTransform:(CGAffineTransform)transform;
+ (NSValue *)valueWithUIEdgeInsets:(UIEdgeInsets)insets;
+ (NSValue *)valueWithUIOffset:(UIOffset)insets NS_AVAILABLE_IOS(5_0);
- (CGPoint)CGPointValue;
- (CGSize)CGSizeValue;
- (CGRect)CGRectValue;
- (CGAffineTransform)CGAffineTransformValue;
- (UIEdgeInsets)UIEdgeInsetsValue;
- (UIOffset)UIOffsetValue NS_AVAILABLE_IOS(5_0);
@end
- UIKeyboardFrameBeginUserInfoKey: 动画前键盘的位置,包含CGRect的NSValue
- UIKeyboardFrameEndUserInfoKey:动画结束后的键盘位置,包含CGRect的NSValue
NSDictionary* info = [aNotification userInfo];
CGRect rect =[[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
- UIKeyboardAnimationDurationUserInfoKey:动画持续时间,数值是NSNumber
- UIKeyboardAnimationCurveUserInfoKey:动画曲线类型(UIViewAnimationCurve),数值是NSNumber
typedef enum {
UIViewAnimationCurveEaseInOut, //淡入淡出,开始时慢,由慢变快,中间最快,然后变慢;
UIViewAnimationCurveEaseIn,//淡入,开始时慢然后越来越快;
UIViewAnimationCurveEaseOut,//淡出,开始快然后越来越慢;
UIViewAnimationCurveLinear//线性匀速,开始和结束是一个速度。
} UIViewAnimationCurve;
- UIKeyboardIsLocalUserInfoKey 是否是原生键盘
- UIKeyboardCenterBeginUserInfoKey 键盘开始的时候中心点位置
- UIKeyboardCenterEndUserInfoKey 键盘结束的时候中心点位置
- UIKeyboardBoundsUserInfoKey:键盘大小
// These keys are superseded by UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey.
翻译:这些钥匙(UIKeyboardCenterBeginUserInfoKey, UIKeyboardCenterEndUserInfoKey, UIKeyboardBoundsUserInfoKey)被UIKeyboardFrameBeginUserInfoKey和UIKeyboardFrameEndUserInfoKey取代。
键盘通知的使用
- 添加键盘监听事件
#pragma mark -添加键盘监听事件
/**
添加键盘监听事件
*/
-(void)addNotificationForKeyboard
{
// 注册键盘通知
//键盘的frame值将要发生变化
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardWillChangeFrameNotification:) name:UIKeyboardWillChangeFrameNotification object:nil];
//键盘的frame值发生变化
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardDidChangeFrameNotification:) name:UIKeyboardDidChangeFrameNotification object:nil];
// 即将显示
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil];
// 显示
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector (keyboardDidShowNotification:) name:UIKeyboardDidShowNotification object:nil];
// 即将隐藏
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHideNotification:) name:UIKeyboardDidHideNotification object:nil];
// 隐藏
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHideNotification:) name:UIKeyboardDidHideNotification object:nil];
}
- 移除键盘监听事件
#pragma mark - 移除键盘监听事件
/**
移除键盘监听事件
*/
- (void)removeNotificationForKeyboard
{
//键盘的frame值将要发生变化
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
//键盘的frame值发生变化
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidChangeFrameNotification object:nil];
// 即将显示
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
// 显示
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
// 即将隐藏
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
// 隐藏
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
}
- 键盘监听方法
#pragma mark -键盘监听方法
- (void) keyboardWillChangeFrameNotification: (NSNotification *)notif{
NSLog(@"键盘的frame值将要发生变化");
}
- (void) keyboardDidChangeFrameNotification: (NSNotification *)notif{
NSLog(@"键盘的frame值已经发生变化");
}
- (void) keyboardWillShowNotification: (NSNotification *)notif{
NSLog(@"键盘即将显示");
}
- (void) keyboardDidShowNotification: (NSNotification *)notif{
NSLog(@"键盘显示");
}
- (void) keyboardWillHideNotification:(NSNotification *)notif{
NSLog(@"键盘即将隐藏");
}
- (void) keyboardDidHideNotification:(NSNotification *)notif{
NSLog(@"键盘隐藏");
}
- notification 中userInfo的完整信息:
/**
{
UIKeyboardAnimationCurveUserInfoKey = 7;
UIKeyboardAnimationDurationUserInfoKey = "0.25";
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 796}";
UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 538}";
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
UIKeyboardIsLocalUserInfoKey = 1;
}
*/
-
键盘通知(NSNotificationCenter)正确使用
- 在界面即将出现的时候注册键盘通知
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; //注册键盘通知 [self addNotificationForKeyboard]; }
- 在页面即将消失的时候移除通知 移除通知要用通知名对应去移除
- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; //移除键盘监听 [self removeNotificationForKeyboard]; }
键盘通知的发出顺序
- 当一个UITextView或UITextField变成第一焦点时,通知的发出顺序如下:
UIKeyboardWillChangeFrameNotification --> UIKeyboardWillShowNotification --> UIKeyboardDidChangeFrameNotification --> UIKeyboardDidShowNotification
- 当一个UITextView或UITextField注销焦点状态时,发出通知顺序如下:
UIKeyboardWillChangeFrameNotification --> UIKeyboardWillHideNotification --> UIKeyboardDidChangeFrameNotification --> UIKeyboardDidHideNotification
- 特别需要注意的是,当屏幕旋转的时候也会发出键盘通知,并且顺序如下:
UIKeyboardWillChangeFrameNotification --> UIKeyboardWillHideNotification --> UIKeyboardDidChangeFrameNotification --> UIKeyboardDidHideNotification --> UIKeyboardWillChangeFrameNotification --> UIKeyboardWillShowNotification --> UIKeyboardDidChangeFrameNotification --> UIKeyboardDidShowNotification
/**
注:其顺序是一个UITextView或UITextField注销焦点状态时,发出键盘通知顺序和一个UITextView或UITextField变成第一焦点时发出键盘顺序组合起来一致,也就是说,在屏幕旋转期间,虽然我们看起来好像键盘没啥变化,但实际上通知已经经理了从“消失”到再次“显示”的路径了。
*/