前言
現(xiàn)就職于一家擁有菜譜分享功能的App的公司,某tableView頁(yè)面,有著相當(dāng)多的textview和textfield,點(diǎn)擊輸入框時(shí)需要進(jìn)行鍵盤的彈出處理,并自動(dòng)滾動(dòng)到相應(yīng)的位置。試了一些網(wǎng)上分享的方法,覺得都不是很好,所以結(jié)合蘋果官方文檔,自己總結(jié)了一下。
正題
1、最容易存在的問題
在鍵盤處理的過程中,最容易出現(xiàn)問題的就是,在鍵盤監(jiān)聽事件中,tableView的frame的修改,網(wǎng)上分享的大部分都是修改frame,這樣會(huì)導(dǎo)致tableView的cell被遮擋,可能引起獲取不到cell的indexPath,導(dǎo)致無法滾動(dòng)到指定位置
還有一點(diǎn)就是UITableViewController的使用,如果直接使用UITableViewController,鍵盤彈出事件是不用我們開發(fā)者去處理的,UITableViewController自動(dòng)幫我們實(shí)現(xiàn)了,也就是點(diǎn)擊cell中的輸入框,就可以直接彈出到可見區(qū)域,進(jìn)行編輯。但UITableViewController的view是一個(gè)tableView,也就是說,你想在這個(gè)controller里加一個(gè)固定位置的view,是不可能的,這就犧牲了頁(yè)面的可定制性
2、如何去實(shí)現(xiàn)
- (void)registerForKeyboardNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)aNotification {
NSDictionary* info = [aNotification userInfo];
// 注意不要用UIKeyboardFrameBeginUserInfoKey,第三方鍵盤可能會(huì)存在高度不準(zhǔn),相差40高度的問題
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
// 修改滾動(dòng)天和tableView的contentInset
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, kbSize.height, 0);
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, kbSize.height, 0);
// 跳轉(zhuǎn)到當(dāng)前點(diǎn)擊的輸入框所在的cell
[UIView animateWithDuration:0.2 animations:^{
[self.tableView scrollToRowAtIndexPath:_indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
}];
}
- (void)keyboardWillBeHidden:(NSNotification *)aNotification {
self.tableView.contentInset = UIEdgeInsetsZero;
self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}
這里我們需要添加對(duì)鍵盤事件通知的檢測(cè),而對(duì)自己的tableView所做的改變,不是frame,而是contentInset,這樣就可以保證tableView的滾動(dòng)范圍為鍵盤上方的區(qū)域,可見區(qū)域?yàn)檎麄€(gè)屏幕。
_indexPath全局變量,需要在textfield的代理中去獲取,獲取到正在編輯的輸入框所在的cell。
- (void)textFieldDidBeginEditing:(UITextField *)textField {
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)textField.superview.superview];
_indexPath = indexPath;
}
3、疑難問題
iOS8之后開始,iOS系統(tǒng)開始支持第三方輸入法了,在第三方鍵盤彈出的時(shí)候,
UIKeyboardWillShowNotification會(huì)有三次通知,
- (void)keyboardWillShow:(NSNotification *)aNotification
方法會(huì)執(zhí)行三次,而三次的鍵盤高度可能是不一樣的,以最后一次高度為準(zhǔn),所以tableView在滾動(dòng)的時(shí)候,默認(rèn)的動(dòng)畫在多次執(zhí)行時(shí),可能會(huì)存在前一個(gè)動(dòng)畫沒執(zhí)行完成,后面的方法就不會(huì)執(zhí)行,從而導(dǎo)致tableView無法滾動(dòng)到目標(biāo)位置的問題。
[self.tableView scrollToRowAtIndexPath:_indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
所以要改成如下的UIView動(dòng)畫,就OK了
[UIView animateWithDuration:0.2 animations:^{
[self.tableView scrollToRowAtIndexPath:_indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
}];
而掌握了以上竅門后,那tableView和scrollView想滾動(dòng)到指定位置,就很簡(jiǎn)單了。