自定義UITextView輸入框

JmoVxia發表於2018-01-22

前言

一款聊天型別的APP,文字輸入框是必不可少的,在此簡單寫了一個Demo供大家參考,希望能夠拋磚引玉。

思路

為了方便封裝UI,將UITextView封裝到一個UIView中。UIView內部需要監聽鍵盤的彈出和消失,根據文字動態計算UITextView的高度,達到指定的最高高度後,UITextView高度不變化,文字自動上移。

1.基本UI框架搭建

UI比較簡單,就不細說了,具體程式碼如下。

-(void)initView {
    self.backgroundColor = [UIColor whiteColor];
    //頂部線條
    self.topLine = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.CLwidth, 1)];
    self.topLine.backgroundColor = RGBACOLOR(0, 0, 0, 0.2);
    [self addSubview:self.topLine];
    //底部線條
    self.bottomLine = [[UIView alloc] initWithFrame:CGRectMake(0, self.CLheight - 1, self.CLwidth, 1)];
    self.bottomLine.backgroundColor = RGBACOLOR(0, 0, 0, 0.2);
    [self addSubview:self.bottomLine];
    //邊框
    self.edgeLineView = [[UIView alloc]init];
    self.edgeLineView.CLwidth = self.CLwidth - 50 - 30;
    self.edgeLineView.CLleft = 10;
    self.edgeLineView.layer.cornerRadius = 5;
    self.edgeLineView.layer.borderColor = RGBACOLOR(0, 0, 0, 0.5).CGColor;
    self.edgeLineView.layer.borderWidth = 1;
    self.edgeLineView.layer.masksToBounds = YES;
    [self addSubview:self.edgeLineView];
    //輸入框
    self.textView = [[UITextView alloc] init];;
    self.textView.CLwidth = self.CLwidth - 50 - 46;
    self.textView.CLleft = 18;
    self.textView.enablesReturnKeyAutomatically = YES;
    self.textView.delegate = self;
    //關閉連續佈局
    self.textView.layoutManager.allowsNonContiguousLayout = NO;
    self.textView.scrollsToTop = NO;
    //去掉自帶的間距
    self.textView.textContainerInset = UIEdgeInsetsZero;
    self.textView.textContainer.lineFragmentPadding = 0;
    [self addSubview:self.textView];
    //佔位文字
    self.placeholderLabel = [[UILabel alloc] init];
    self.placeholderLabel.CLwidth = self.textView.CLwidth - 10;
    self.placeholderLabel.textColor = RGBACOLOR(0, 0, 0, 0.5);
    self.placeholderLabel.CLleft = 23;
    [self addSubview:self.placeholderLabel];
    //傳送按鈕
    self.sendButton = [[UIButton alloc] initWithFrame:CGRectMake(self.CLwidth - 50 - 10, self.CLheight - 30 - 10, 50, 30)];
    [self.sendButton.layer setBorderWidth:1.0];
    [self.sendButton.layer setCornerRadius:5.0];
    self.sendButton.layer.borderColor = RGBACOLOR(0, 0, 0, 0.5).CGColor;
    self.sendButton.enabled = NO;
    self.sendButton.titleLabel.font = [UIFont systemFontOfSize:16];
    [self.sendButton setTitle:@"傳送" forState:UIControlStateNormal];
    [self.sendButton setTitleColor:RGBACOLOR(0, 0, 0, 0.2) forState:UIControlStateNormal];
    [self.sendButton addTarget:self action:@selector(didClicksendButton) forControlEvents:UIControlEventTouchUpInside];
    [self addSubview:self.sendButton];
    self.fontSize = 20;
    self.textViewMaxLine = 3;
}
複製程式碼

2.監聽鍵盤彈出和收回

輸入框需要跟隨鍵盤的彈出和收回,監聽鍵盤相對應的通知事件,根據鍵盤彈出時間等做出相應的處理。

#pragma mark keyboardnotification
- (void)keyboardWillShow:(NSNotification *)notification {
    CGRect keyboardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    _keyboardHeight = keyboardFrame.size.height;
    CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    [UIView animateWithDuration:duration animations:^{
        self.CLy = keyboardFrame.origin.y - self.CLheight;
    }];
}
- (void)keyboardWillHidden:(NSNotification *)notification {
    CGFloat duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    [UIView animateWithDuration:duration animations:^{
        self.CLy = CLscreenHeight;
    }];
}
複製程式碼

3.根據文字動態改變輸入框高度

在UITextView代理中,通過文字計算需要的高度,判斷是否達到最大高度,沒有達到的情況就改變輸入框的高度,超過最大高度,文字上移,高度不變。

#pragma mark UITextViewDelegate
- (void)textViewDidChange:(UITextView *)textView {
    self.placeholderLabel.hidden = textView.text.length;
    if (textView.text.length == 0) {
        self.sendButton.enabled = NO;
        [self.sendButton setTitleColor:RGBACOLOR(0, 0, 0, 0.2) forState:UIControlStateNormal];
    }else{
        self.sendButton.enabled = YES;
        [self.sendButton setTitleColor:RGBACOLOR(0, 0, 0, 1.0) forState:UIControlStateNormal];
    }
    CGFloat contentSizeH = textView.contentSize.height;
    CGFloat lineH = textView.font.lineHeight;
    CGFloat maxTextViewHeight = ceil(lineH * self.textViewMaxLine + textView.textContainerInset.top + textView.textContainerInset.bottom);
    if (contentSizeH <= maxTextViewHeight) {
        textView.CLheight = contentSizeH;
    }else{
        textView.CLheight = maxTextViewHeight;
    }
    self.CLheight = ceil(textView.CLheight) + 10 + 10;
    self.CLbottom = CLscreenHeight - _keyboardHeight;
    [textView scrollRangeToVisible:NSMakeRange(textView.selectedRange.location, 1)];
}
複製程式碼

介面

簡單封裝了一下,給出了一些介面,具體如下。

/**設定輸入框最大行數*/
@property (nonatomic, assign) NSInteger textViewMaxLine;
/**輸入框文字大小*/
@property (nonatomic, assign) CGFloat fontSize;
/**佔位文字*/
@property (nonatomic, copy) NSString *placeholder;

/**收回鍵盤*/
-(void)bounceToolbar;
/**彈出鍵盤*/
- (void)popToolbar;
/**點選傳送後的文字*/
- (void)inputToolbarSendText:(inputTextBlock)sendText;
複製程式碼

效果圖

自定義UITextView輸入框
自定義UITextView輸入框

其他

1.修改游標寬高

自定義一個繼承自UITextView的控制元件,內部重寫下面方法即可。

- (CGRect)caretRectForPosition:(UITextPosition *)position
{
    CGRect originalRect = [super caretRectForPosition:position];
    
    originalRect.size.width = 2;
    originalRect.size.height = self.font.lineHeight;

    return originalRect;
}
複製程式碼

2.修改游標顏色

[self.textView setTintColor:[UIColor redColor]];
複製程式碼

3.修改行間距

NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.lineSpacing = 20;// 字型的行間距    
NSDictionary *attributes = @{
                                 NSFontAttributeName:[UIFont systemFontOfSize:17],
                                 NSParagraphStyleAttributeName:paragraphStyle
                                 };
self.textView.typingAttributes = attributes;
複製程式碼

總結

程式碼比較簡單,完整專案地址------>CLInputToolbar

相關文章