1、鍵盤遮擋的場景分類ios
NSDictionary *userInfo = [notification userInfo];app
NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];iphone
CGRect keyboardRect = [aValue CGRectValue];async
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];ide
CGFloat keyboardTop = keyboardRect.origin.y;函數
CGFloat margin = 20;//文本框距鍵盤頂邊最小距離測試
CGRect textFieldFrame = [self.viewconvertRect:_textFieldCall4Adjust.framefromView: _textFieldCall4Adjust.superview];動畫
CGFloat textFieldBottom = textFieldFrame.origin.y + textFieldFrame.size.height;ui
CGFloat delta = textFieldBottom + margin - keyboardTop;atom
[UIView setAnimationCurve:[[[notif userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView animateWithDuration:[[[notif userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^(){
UIKeyboardWillShowNotification, UIKeyboardDidShowNotification, UIKeyboardWillHideNotification, UIKeyboardDidHideNotification,
UIKeyboardWillChangeFrameNotification, UIKeyboardDidChangeFrameNotification, UIApplicationWillChangeStatusBarOrientationNotification, UIApplicationDidChangeStatusBarOrientationNotification
iOS7 | iOS8 | iOS9 | |
1. 新得到焦點 | UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
2.失去焦點 | UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification |
3.切換焦點 | 無(新舊鍵盤相同或等高) | 無(新舊鍵盤相同或等高) | 無(新舊鍵盤相同或等高) |
4.更換英文至中文輸入法,並輸入中文字符使得鍵盤增高 | UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification
(開啓輸入預測增長一個循環) UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification
(切換時無,即時開閉輸入預測代入一次循環) UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification
|
5.更換中文(有多一行)至英文 | UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification
(開啓輸入預測增長一個循環) UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification
(切換時無,即時開閉輸入預測代入一次循環) UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
6.轉屏 | UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification UIApplicationWillChangeStatusBarOrientationNotification UIApplicationDidChangeStatusBarOrientationNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification
(willShow的時候鍵盤爲舊轉向frame) didShow時鍵盤爲新轉向frame |
UIApplicationWillChangeStatusBarOrientationNotification UIApplicationDidChangeStatusBarOrientationNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification
(輸入預測開啓無關)
|
UIApplicationWillChangeStatusBarOrientationNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification UIApplicationDidChangeStatusBarOrientationNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillShowNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidShowNotification |
7.滑動隱藏鍵盤 | UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification
UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification |
UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification UIKeyboardWillChangeFrameNotification UIKeyboardWillHideNotification
UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification UIKeyboardDidChangeFrameNotification UIKeyboardDidHideNotification |
2. willShow,willHide爲最佳同步鍵盤動畫時機。但爲適配iOS67屏. 選擇willShow, didShow, willHide三個鍵盤通知做鍵盤適應事件處理入口
3. 切換焦點需另做處理獲取事件處理時機
4. 轉屏時,willShow, didShow, willHide事件,如將動畫合併提交,可能會不符合預想
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// 在子類中應調用該方法
if (_textFieldFocusing && _textFieldFocusing.isFirstResponder && _textFieldFocusing != textField ) {
// 處理切換輸入焦點不會發出鍵盤SHOW通知的問題
_textFieldFocusing = textField;
[self p_handleKeyboardShow:nil];
} else {
_textFieldFocusing = textField;
}
return YES;
}
SubClass:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if (textField.tag == TagCouldNotEdit) {
return NO;
}
return [super textFieldShouldBeginEditing:textField];;
}
b.切換焦點時,沒法獲取鍵盤frame,所以需保存最近一次鍵盤通知
notification = notification?:oldKeyBoardNoti;
if (!notification) {
return;
}
oldKeyBoardNoti = notification;
2. 鍵盤處理事件串行化處理
每次動畫提交同步至上次動畫結束。
dispatch_semaphore_t semaphore;
dispatch_queue_t queue;
。。。。
semaphore = dispatch_semaphore_create(1);
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- (void) keyboardDidShow:(NSNotification *) notif {
if (!self.textFieldFocusing || ![self.textFieldFocusingisFirstResponder]) {
return;
}
// 轉屏支持
// iphone7, ios4轉屏時只走一遍hide->show,並且willShow時鍵盤尺寸異常
[self p_handleKeyboardShow:notif];
}
-(void)keyboardWillShow:(NSNotification *)notification {
if (!self.textFieldFocusing || ![self.textFieldFocusingisFirstResponder]) {
return;
}
[self p_handleKeyboardShow:notification];
}
- (void) p_handleKeyboardShow:(NSNotification *)notification {
notification = notification?:oldKeyBoardNoti;
if (!notification) {
return;
}
oldKeyBoardNoti = notification;
// 第一次鍵盤出現,且未獲取tableView的contentSize時,獲取tableview的size
// 最多隻執行一次
if (_idealTableViewSizeHeight == 0) {
_idealTableViewSizeHeight = self.tableView.contentSize.height;
}
// 動畫塊
void (^changeContentOffset)() = ^(){
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView animateWithDuration:([[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]?:0.2) animations:^(){
// @IMPORTANT 每次block動畫任務被執行時,從新計算移動距離
// 需操做的環境參數
NSDictionary *userInfo = [notification userInfo];
NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
CGFloat keyboardTop = keyboardRect.origin.y;
CGFloat margin = 20;//文本框距鍵盤頂邊最小距離
CGRect textFieldFrame = [self.viewconvertRect:_textFieldFocusing.framefromView:_textFieldFocusing.superview];
CGFloat textFieldBottom = textFieldFrame.origin.y + textFieldFrame.size.height;
CGFloat delta = textFieldBottom + margin - keyboardTop;
CGFloat contentSizeHeight = MAX( self.tableView.frame.size.height, self.tableView.contentSize.height);
[self.tableViewsetContentSize:CGSizeMake(self.view.frame.size.width, contentSizeHeight + delta)];
[self.tableView setContentOffset: CGPointMake(0, delta + oldTableViewOffset.y) animated:NO];
} completion:^(BOOL finished) {
dispatch_async( queue, ^{
dispatch_semaphore_signal(semaphore);
});
}];
};
// 串行動畫控制
dispatch_async(queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 需操做的環境參數
NSDictionary *userInfo = [notification userInfo];
NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
CGFloat keyboardTop = keyboardRect.origin.y;
CGFloat margin = 20;//文本框距鍵盤頂邊最小距離
CGRect textFieldFrame = [self.viewconvertRect:_textFieldFocusing.framefromView:_textFieldFocusing.superview];
CGFloat textFieldBottom = textFieldFrame.origin.y + textFieldFrame.size.height;
if ( !self.textFieldFocusing
|| ![self.textFieldFocusing isFirstResponder]
|| textFieldBottom + margin <= keyboardTop
|| fabs(textFieldBottom + margin - keyboardTop) < 0.1) {
// 不須要執行動畫
dispatch_semaphore_signal(semaphore);
} else {
oldTableViewOffset = self.tableView.contentOffset;
dispatch_async(dispatch_get_main_queue(), ^{
changeContentOffset();
});
}
});
}
- (void) keyboardWillHide:(NSNotification *) notif {
// 經過drag隱藏時,會兩次發出鍵盤隱藏通知,但對UI目前沒有影響,不作緣由查找
// 動畫塊
void (^changeContentOffset)() = ^(){
self.tableView.bounces = NO;
[UIView setAnimationCurve:[[[notif userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
[UIView animateWithDuration:[[[notif userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue] animations:^(){
[self.tableViewsetContentSize:CGSizeMake(self.view.frame.size.width,_idealTableViewSizeHeight)];
} completion:^(BOOL finished) {
self.tableView.bounces = YES;
dispatch_async(queue, ^{
dispatch_semaphore_signal(semaphore);
});
}] ;
};
// 串行動畫控制
dispatch_async( queue, ^{
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
if (self.tableView.contentSize.height <_idealTableViewSizeHeight
|| fabs(self.tableView.contentSize.height - _idealTableViewSizeHeight)<0.1) {
// 不須要執行動畫
dispatch_semaphore_signal(semaphore);
} else {
dispatch_async(dispatch_get_main_queue(), ^{
changeContentOffset();
});
}
});
}
7、自定義鍵盤
1.iputView
注意,當inputView的ViewController自定義,inputView的相關響應方法寫在ViewController時,使用三方鍵盤可能發生異常
禁用三方鍵盤方法
- (BOOL)application:(UIApplication *)application shouldAllowExtensionPointIdentifier:(NSString *)extensionPointIdentifier
{
if ([extensionPointIdentifier isEqualToString: UIApplicationKeyboardExtensionPointIdentifier])
{
return NO;
}
return YES;
}
2.UIInputViewController
UIResponder的inputViewController爲readOnly,須要強制改成readWrite
@interface TextField:UITextField
@property (nonatomic, readwrite, strong) UIInputViewController*inputViewController;
@end
@implementation TextField
@end
3.Application Extension
先新建Application,而後新建customed Keyboard Target, XCode將生成基礎代碼。開發時不能用Interface Builder, 必須所有代碼手寫