UITableView+UIScrollView的鍵盤彈出處理

前言

現(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)單了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容