iOS仿微信輸入框,限制最大行數(shù),一體鍵盤(兩種思路)

緣由

看了很多輸入框,處理的最好的,就是微信,QQ,以及支付寶,其他的看了不少,包括百思,簡書,same.微信,QQ,支付寶的就不做gif了。百思之前的版本輸入框做的也不好,后來反饋了之后換了一種方式而已。拿簡書和same舉個列子。(ps:same 是同事推薦,我也不知道是什么軟件,此處沒有打廣告)

簡書:

自定義.gif

可以看到在返回的時候輸入框會跳躍到鍵盤下方,然后很快再出來。(做的好的會一體返回)

E5EF4AD0-F34D-43E8-83D7-FA903777CCA0.png

問題2:在限制多行之后,就會出現(xiàn)最上面的一行顯示不全。

same

same.gif

問題:same的輸入框和簡書的如出一轍,在側(cè)滑返回的時候會跳躍。

有兩種思路,推薦第二種。第一種因?yàn)橛邢到y(tǒng)默認(rèn)的上下間距,動畫效果不好。第二種我們可以關(guān)閉掉系統(tǒng)的默認(rèn)間距,為textView添加一個假的上下間距,動畫會比較自然。

第一種:利用textview自定義鍵盤,限制多行輸入。

關(guān)于跳躍問題,實(shí)現(xiàn)一體鍵盤,參考文章:iOS 怎么做成和微信一樣的一體鍵盤?

限制多行問題,討論一下。

UITextView有默認(rèn)的上下間距是8,打印textContainerInset是可以測出來的。微信的輸入框在單行的時候保持了默認(rèn)的上下間距8,但是在大于一行文字后上下間距就會變化。

為了做的和微信輸入框很像,我們在限制了最大行數(shù)之后,可以設(shè)置textViewsetContentOffset屬性,滾動距離為(當(dāng)前行數(shù) - 限制的最大行數(shù))* lineHeight + 上邊距。即可。為了過渡效果,在超出限制最大行數(shù)時候關(guān)閉掉系統(tǒng)的默認(rèn)動畫[self.textView setContentOffset:point animated:NO],否則在回退的時候會很丑,在小于最大行數(shù)是使用系統(tǒng)的動畫效果[self.textView setContentOffset:CGPointZero animated:YES];

 if (line >self.maxLine) {
        
        CGPoint point = CGPointMake(0, (line -self.maxLine) *lineH +8 );
        [self.textView setContentOffset:point animated:NO];
        self.textView.lx_height = ceil(self.maxLine *lineH +8);
        
    }else{
        self.textView.lx_height = contentSizeH;
        [self.textView setContentOffset:CGPointZero animated:YES];
        

還有一點(diǎn)需要說明,輸入框的初始高度,因?yàn)閠extView的默認(rèn)上下間距,我們需要計(jì)算好初始高度,經(jīng)過測試,如果textView font大小為16時,系統(tǒng)的默認(rèn)高度最好設(shè)置為36. 當(dāng)textView font大小為16時,lineHeight為19.09,加上上下間距為35.09,系統(tǒng)取了36.
所以初始化高度為:

 CGFloat orignTextH  = ceil (TEXTFONT.lineHeight + 16);
 self.frame =  CGRectMake(0, Device_Height - orignTextH, Device_Width, orignTextH);

一體鍵盤的處理:

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

    NSDictionary *userInfo = notification.userInfo;
    // 動畫的持續(xù)時間
    double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    
    // 鍵盤的frame
    CGRect keyboardF = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
//        NSLog(@"%@",NSStringFromCGRect(keyboardF));
    keyboardY = keyboardF.origin.y;

    if (!_isDisappear) {

        [self dealKeyBoardWithKeyboardF:keyboardY duration:duration];
       
    }


}

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

    NSDictionary *userInfo = notification.userInfo;
    // 動畫的持續(xù)時間
    double duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    // 鍵盤的frame
    CGRect keyboardF = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
//        NSLog(@"%@",NSStringFromCGRect(keyboardF));

    keyboardY = keyboardF.origin.y;
//    // 工具條的Y值 == 鍵盤的Y值 - 工具條的高度
    if (_isDisappear) {
        [self dealKeyBoardWithKeyboardF:keyboardY duration:duration];
    }

}
#pragma mark---處理高度---
-(void)dealKeyBoardWithKeyboardF:(CGFloat)keyboardY duration:(CGFloat)duration {
    
    if (!_isDisappear) {
        [UIView animateWithDuration:duration animations:^{
            // 工具條的Y值 == 鍵盤的Y值 - 工具條的高度
            
            if (keyboardY > Device_Height) {
                self.lx_y = Device_Height- self.lx_height;
            }else
            {
                self.lx_y = keyboardY - self.lx_height;
            }
        }];
    }else{
        if (keyboardY > Device_Height) {
            self.lx_y = Device_Height- self.lx_height;
        }else
        {
            self.lx_y = keyboardY - self.lx_height;
        }
    }
    
  
}

第二種 關(guān)閉掉系統(tǒng)對textView的默認(rèn)間距。

如圖,我們給textView一個上下間距,然后再做動畫就比較自然.

QQ20180117-113857.png

#pragma mark---getter---
-(LXTextView *)textView{
    if (!_textView) {
        _textView =[[LXTextView alloc]initWithFrame:CGRectMake(0, self.topOrBottomEdge, self.lx_width - 60, ceil(self.font.lineHeight))];
        _textView.font = self.font;
        _textView.delegate = self;
        _textView.layoutManager.allowsNonContiguousLayout = NO;
         _textView.enablesReturnKeyAutomatically = YES;
        _textView.scrollsToTop = NO;
        _textView.textContainerInset = UIEdgeInsetsZero; //關(guān)閉textview的默認(rèn)間距屬性
        _textView.textContainer.lineFragmentPadding = 0;
        _textView.placeholder = @"發(fā)表評論:";
    }
    return _textView;
}

在處理文字變化的代理方法更改如下:

-(void)textViewDidChange:(UITextView *)textView{
    
    CGFloat contentSizeH = self.textView.contentSize.height;
    CGFloat lineH = self.textView.font.lineHeight;
    
    CGFloat maxHeight = ceil(lineH * self.maxLine + textView.textContainerInset.top + textView.textContainerInset.bottom);
    if (contentSizeH <= maxHeight) {
        self.textView.lx_height = contentSizeH;
    }else{
        self.textView.lx_height = maxHeight;
    }
    
    [textView scrollRangeToVisible:NSMakeRange(textView.selectedRange.location, 1)];
  
    
    CGFloat totalH = ceil(self.textView.lx_height) + 2 * self.topOrBottomEdge;
    self.frame = CGRectMake(0, keyboardY - totalH, self.lx_width, totalH);
   
  
    self.sendBtn.lx_height = totalH;
    self.line.lx_height = totalH - 10;
    
}

補(bǔ)充一點(diǎn):為了適配iOS11以下,需要處理textView,否則xcode9寫的代碼在iOS11以下的設(shè)備上跑的時候回跳動。
textView做如下處理:

if (@available(iOS 11.0, *)) {
            self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        }

控制器中添加處理:

 if (@available(iOS 11.0, *)) {
      
    } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        // 這部分使用到的過期api
        self.automaticallyAdjustsScrollViewInsets = NO;
#pragma clang diagnostic pop
    }
自定義.gif

demo中沒有第一種效果,上面就是探路的思路。demo中的第二種效果支持代碼以及XIB創(chuàng)建keyboard.

demo 地址:一體鍵盤,限制最大行數(shù)

博客推薦:https://4xx.me

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

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

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