另一种思路监听键盘的隐藏与显示

2016-03-21

监听键盘的隐藏与显示

监听键盘的隐藏与显示,其实原始的比较简单,只需要观察四个通知名称:

`UIKeyboardWillShowNotification` 
`UIKeyboardWillHideNotification`
`UIKeyboardDidShowNotification`
`UIKeyboardDidHideNotification`

实现方式是这样的

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

`[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector    (keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];`
`[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];`

`[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector    (keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];`
1
2
3
4
-(void)keyboardWillHide:(NSNotification*)aNotification{
//代码
}

1
2
3
4
-(void)keyboardWillShow:(NSNotification*)aNotification{
//代码
}

1
2
3
4
-(void)keyboardDidHide:(NSNotification*)aNotification{
//代码
}

1
2
3
4
-(void)keyboardDidShow:(NSNotification*)aNotification{
//代码
}

但是,在我的项目里面,如果使用以上方法去监听键盘的隐藏与显示,会编写比较多的代码以及代码逻辑判断很复杂,还有就是,在系统键盘与第三方键盘之间切换时,有时候不会走这个方法,因此,我就换了一种思路去解决这样的bugs,我仅仅是通过监听UIKeyboardWillChangeFrameNotification这个通知,然后通过键盘的y坐标与屏幕高度作比较,如果y值 大于或者等于屏幕高度则为键盘隐藏,相反,y值小于屏幕高度则为键盘显示。这样既可以解决第三方键盘 的高度变化的问题,又可以少写代码。没有代码展示都是耍流氓!
代码如下:
.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

typedef void(^GRUCAnimationsWithKeyboardBlock)(CGRect keyboardRect,CGFloat keyboardOffset,NSTimeInterval duration,BOOL isShowing);
typedef void(^GRUCBeforeAnimationsWithKeyboardBlock)(CGRect keyboardRect,CGFloat keyboardOffset,NSTimeInterval duration,BOOL isShowing);
typedef void(^GRUCCompletionKeyboardAnimationsBlock)(BOOL finished);
typedef void(^GRUCCompletionBeforeUnsubscribeKeyboardBlcok)(void);


@interface GRUCChatPanelView (KeyboardAnimation)
@property (nonatomic,assign) CGFloat yOffset; // keyboard offset if yOfset < 0, the keyboard is Showing,otherwise, it is Hiddening.

/**
* To the notification center, subscribe to a change in the keyboard position of the observer.
* The name of the object observered is 'UIKeyboardWillChangeFrameNotification'.
* @param animations perform the same as the keyboard animations.
* @param completion after the keyboard animations completion, Maybe you have other things to do.
*/

- (void)gruc_subscribeKeyboardWithAnimations:(GRUCAnimationsWithKeyboardBlock)animations completion:(GRUCCompletionKeyboardAnimationsBlock)completion;
- (void)gruc_subscribeUIkeyboardNotification;

/**
* To the notification center,subscribe to a change in the keyboard postion ofhte observer.
*
* @param beforeAnimations before performing the keyboard animations,Maybe you have other things to do.
* @param animations perform the keyboard animations.
* @param completion the keyboard animaitons completion.
*/

- (void)gruc_subscribeKeyboardWithBeforeAnimations:(GRUCBeforeAnimationsWithKeyboardBlock)beforeAnimations
animations:(GRUCAnimationsWithKeyboardBlock)animations
completion:(GRUCCompletionKeyboardAnimationsBlock)completion;


/**
* Cancel subscriber for change the postion of the keyboard.
*/
- (void)gruc_unsubscribeKeyboard;
- (void)gruc_unsubscribeUIKeyboardNotification;

/**
* Cancel subcriber for change the postion of the keyboard. but before canceling subcriber,Maybe you have other things to do.
*
* @param completion completion context.
*/

- (void)gruc_beforeUnsubscribeKeyboard:(GRUCCompletionBeforeUnsubscribeKeyboardBlcok)completion;

.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

-(void)gruc_subscribeKeyboardWithAnimations:(GRUCAnimationsWithKeyboardBlock)animations completion:(GRUCCompletionKeyboardAnimationsBlock)completion{
[self gruc_subscribeKeyboardWithBeforeAnimations:nil animations:animations completion:completion];
}
-(void)gruc_subscribeKeyboardWithBeforeAnimations:(GRUCBeforeAnimationsWithKeyboardBlock)beforeAnimations animations:(GRUCAnimationsWithKeyboardBlock)animations completion:(GRUCCompletionKeyboardAnimationsBlock)completion{
[self gruc_unsubscribeKeyboard];
objc_setAssociatedObject(self, GRUCBeforeAnimationsBlockAssociationKey, beforeAnimations, OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, GRUCAnimationsBlockAssociationKey, animations, OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, GRUCAnimationsCompletionBlockAssociationKey, completion, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self gruc_subscribeUIkeyboardNotification];
}
-(void)gruc_subscribeUIkeyboardNotification{
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(gruc_keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
}
-(void)gruc_unsubscribeKeyboard{
[self gruc_beforeUnsubscribeKeyboard:nil];
}
-(void)gruc_unsubscribeUIKeyboardNotification{
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
}
-(void)gruc_beforeUnsubscribeKeyboard:(GRUCCompletionBeforeUnsubscribeKeyboardBlcok)completion{
if (completion) {
completion();
}
objc_setAssociatedObject(self, GRUCBeforeAnimationsBlockAssociationKey, nil, OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, GRUCAnimationsBlockAssociationKey, nil, OBJC_ASSOCIATION_COPY_NONATOMIC);
objc_setAssociatedObject(self, GRUCAnimationsCompletionBlockAssociationKey, nil, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self gruc_unsubscribeUIKeyboardNotification];
}

#pragma mark -
#pragma mark -- private methods

-(void)gruc_keyboardWillChangeFrame:(NSNotification *)notification{

BOOL isShowing;
NSDictionary *info = [notification userInfo];
CGFloat duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGRect beginKeyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGRect endKeyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

UIViewAnimationCurve curve = (UIViewAnimationCurve)[[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
CGFloat offset = endKeyboardRect.origin.y - beginKeyboardRect.origin.y;
self.yOffset += offset;

isShowing = endKeyboardRect.origin.y >= kScreenHeight ?NO:YES;

GRUCAnimationsWithKeyboardBlock animationsBlock = objc_getAssociatedObject(self, GRUCAnimationsBlockAssociationKey);
GRUCBeforeAnimationsWithKeyboardBlock beforeAnimationsBlock = objc_getAssociatedObject(self, GRUCBeforeAnimationsBlockAssociationKey);
GRUCCompletionKeyboardAnimationsBlock completionBlock = objc_getAssociatedObject(self, GRUCAnimationsCompletionBlockAssociationKey);

if (beforeAnimationsBlock) {
beforeAnimationsBlock(endKeyboardRect,offset,duration,isShowing);
}

[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
[UIView setAnimationCurve:curve];
if (animationsBlock) {
animationsBlock(endKeyboardRect,offset,duration,isShowing);
}
} completion:completionBlock];

}
-(CGFloat)yOffset{
return [objc_getAssociatedObject(self, externVarableKey) doubleValue];
}
-(void)setYOffset:(CGFloat)yOffset{
objc_setAssociatedObject(self, externVarableKey, @(yOffset), OBJC_ASSOCIATION_COPY_NONATOMIC);
}

总结

如有发现bugs,请联系`woodjobber@outlook.com`

项目地址:https://github.com/woodjobber/GRUCChatPanelView

微信公众号:嘀咕嘀咕(iOSSharers)

扫二维码关注