目前能够实现的功能:
- 设置占位字符,可以设置占位字符的字体大小,字体颜色,字体高亮颜色,也可以设置属性字符串作为占位字符
- 设置最大行数,超过最大行数之后滚动显示
- 设置最多输入的文字个数,超过之后不能输入,并触发block回调
- 设置输入框的圆角弧度
- 设置光标的宽度和高度
直接上代码:
.h文件:
//
// KPTextView.h
//
// 使用时至少实现 占位文字内容 和 文字的字体大小
//
// Created by 刘鲲鹏 on 2017/5/12.
// Copyright © 2017年 刘鲲鹏. All rights reserved.
//
#import <UIKit/UIKit.h>
typedef void(^KP_textHeightChangedBlock)(NSString *text,CGFloat textHeight);
typedef void(^KP_textViewLengthOverLimitBlock)(NSInteger maxLengthOfText);
@interface KPTextView : UITextView
/**
* 普通字符串 占位文字
*/
@property (nonatomic, strong) NSString *placeholder;
/**
* 属性字符串 占位文字
*/
@property (nonatomic, strong) NSAttributedString *attributedPlaceHolder;
/**
* 占位文字颜色,默认为亮灰色
*/
@property (nonatomic, strong) UIColor *placeholderColor;
/**
* 占位文字高亮颜色,默认为亮灰色
*/
@property (nonatomic, strong) UIColor *placeholderHighLightColor;
/**
* 占位符字体大小
*/
@property (nonatomic,strong) UIFont *placeholderFont;
/**
* textView最大行数,默认没有高度限制
*/
@property (nonatomic, assign) NSUInteger maxNumberOfLines;
/**
* textView可以输入的最大字数,默认没有字数限制
*/
@property (nonatomic, assign) NSUInteger maxLengthOfText;
/**
* 设置边框宽度,默认为1
*/
@property (nonatomic, assign) NSUInteger borderWidth;
/**
* 设置边框颜色,默认为亮灰色
*/
@property (nonatomic, strong) UIColor *borderColor;
/**
* 设置圆角,默认没有圆角
*/
@property (nonatomic, assign) NSUInteger cornerRadius;
/**
* 光标宽度,默认为2
*/
@property (nonatomic, assign) NSUInteger cursorWidth;
/**
* 光标高度,默认为 self.font.lineHeight + 4
*/
@property (nonatomic, assign) NSUInteger cursorHeight;
/**
* 文字高度改变会自动调用
* block参数(text) → 文字内容
* block参数(textHeight) → 文字高度
*/
@property (nonatomic, strong) KP_textHeightChangedBlock textChangedBlock;
/**
* 文字字数超出设定值会自动调用
* block参数(maxLengthOfText) → 文字长度最大值
*/
@property (nonatomic, strong) KP_textViewLengthOverLimitBlock textOverLimitBlock;
- (void)textValueDidChanged:(KP_textHeightChangedBlock)block;
- (void)textLengthOverLimit:(KP_textViewLengthOverLimitBlock)block;
@end
.m文件:
//
// KPTextView.m
// textViewDemo
//
// Created by 刘鲲鹏 on 2017/5/12.
// Copyright © 2017年 刘鲲鹏. All rights reserved.
//
#import "KPTextView.h"
@interface KPTextView ()
{
UIColor *NormalColor;
}
/**
* UILabel作为placeholderView,解决占位符问题.
*/
@property (nonatomic, weak) UILabel *placeholderView;
/**
* 文字高度
*/
@property (nonatomic, assign) NSInteger textH;
/**
* 文字最大高度
*/
@property (nonatomic, assign) NSInteger maxTextH;
/**
* textView设定的高度
*/
@property (nonatomic, assign) NSInteger textViewSettingHeight;
@end
@implementation KPTextView
- (UILabel *)placeholderView {
if (!_placeholderView ) {
UILabel *placeholderView = [[UILabel alloc] init];
_placeholderView = placeholderView;
//防止textView输入时跳动问题
// _placeholderView.scrollEnabled = NO;
// _placeholderView.showsHorizontalScrollIndicator = NO;
// _placeholderView.showsVerticalScrollIndicator = NO;
_placeholderView.userInteractionEnabled = NO;
_placeholderView.font = self.font;
_placeholderView.backgroundColor = [UIColor clearColor];
_placeholderColor = [UIColor lightGrayColor];
_placeholderView.textColor = _placeholderColor;
_placeholderView.numberOfLines = 0;
_maxNumberOfLines = NSIntegerMax;
[self addSubview:placeholderView];
}
return _placeholderView;
}
- (void)setMaxNumberOfLines:(NSUInteger)maxNumberOfLines {
_maxNumberOfLines = maxNumberOfLines;
/**
* 根据最大的行数计算textView的最大高度
* 计算最大高度 = (每行高度 * 总行数 + 文字上下间距)
*/
_maxTextH = ceil(self.font.lineHeight * maxNumberOfLines + self.textContainerInset.top + self.textContainerInset.bottom);
}
- (void)setBorderWidth:(NSUInteger)borderWidth {
_borderWidth = borderWidth;
self.layer.borderWidth = _borderWidth;
}
- (void)setBorderColor:(UIColor *)borderColor {
_borderColor = borderColor;
self.layer.borderColor = _borderColor.CGColor;
}
- (void)setCornerRadius:(NSUInteger)cornerRadius {
_cornerRadius = cornerRadius;
self.layer.cornerRadius = cornerRadius;
}
/**
* 通过设置placeholderColor设置私有属性placeholderView中的textColor
*/
- (void)setPlaceholderColor:(UIColor *)placeholderColor {
static dispatch_once_t once;
dispatch_once(&once, ^{
NormalColor = placeholderColor;
});
_placeholderColor = placeholderColor;
self.placeholderView.textColor = placeholderColor;
}
/**
* 通过设置placeholder设置私有属性placeholderView中的text
*/
- (void)setPlaceholder:(NSString *)placeholder {
_placeholder = placeholder;
self.placeholderView.text = placeholder;
}
/**
* 通过设置attributedPlaceHolder设置私有属性placeholderView中的attributedText
*/
- (void)setAttributedPlaceHolder:(NSAttributedString *)attributedPlaceHolder {
_attributedPlaceHolder = attributedPlaceHolder;
self.placeholderView.attributedText = attributedPlaceHolder;
}
/**
* 通过设置_placeholderFont设置私有属性placeholderView中的Font
*/
- (void)setPlaceholderFont:(UIFont *)placeholderFont {
_placeholderFont = placeholderFont;
self.placeholderView.font = placeholderFont;
if (self.font && _placeholderFont) {
}
}
- (void)setFont:(UIFont *)font {
[super setFont:font];
self.placeholderView.frame = CGRectMake(7, 8, self.bounds.size.width, font.lineHeight);
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setup];
}
return self;
}
- (void)setup {
self.scrollEnabled = NO;
self.scrollsToTop = NO;
self.showsHorizontalScrollIndicator = NO;
self.enablesReturnKeyAutomatically = YES;
self.layer.borderWidth = 1;
self.layer.borderColor = [UIColor lightGrayColor].CGColor;
_textViewSettingHeight = self.frame.size.height;
//实时监听textView值得改变
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange) name:UITextViewTextDidChangeNotification object:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBeginEditing) name:UITextViewTextDidBeginEditingNotification object:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEndEditing) name:UITextViewTextDidEndEditingNotification object:self];
}
- (void)textDidChange {
NSInteger wordCount = self.text.length;
// NSLog(@"%ld",(long)wordCount);
if (_maxLengthOfText && wordCount >= _maxLengthOfText) {
self.text = [self.text substringToIndex:_maxLengthOfText];
if (_textOverLimitBlock) {
_textOverLimitBlock(_maxLengthOfText);
}
}
// 根据文字内容决定placeholderView是否隐藏
self.placeholderView.hidden = self.hasText;
NSInteger height = ceilf([self sizeThatFits:CGSizeMake(self.bounds.size.width, MAXFLOAT)].height);
if (_textH != height) { // 高度不一样,就改变了高度
// 当高度大于最大高度时,需要滚动
self.scrollEnabled = height > _maxTextH && _maxTextH > 0;
_textH = height;
//当不可以滚动(即 <= 最大高度)时,传值改变textView高度
if (_textChangedBlock && self.scrollEnabled == NO && height > _textViewSettingHeight) {
_textChangedBlock(self.text,height);
[self.superview layoutIfNeeded];
// self.placeholderView.frame = self.bounds;
}
}
}
- (void)didBeginEditing {
if (_placeholderHighLightColor) {
self.placeholderColor = _placeholderHighLightColor;
}else {
self.placeholderColor = [UIColor lightGrayColor];
}
}
- (void)didEndEditing {
self.placeholderColor = NormalColor;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)textValueDidChanged:(KP_textHeightChangedBlock)block {
_textChangedBlock = block;
}
- (void)textLengthOverLimit:(KP_textViewLengthOverLimitBlock)block {
_textOverLimitBlock = block;
}
- (CGRect)caretRectForPosition:(UITextPosition *)position
{
CGRect originalRect = [super caretRectForPosition:position];
if (_cursorHeight) {
originalRect.size.height = _cursorHeight;
}else {
originalRect.size.height = self.font.lineHeight + 4;
}
if (_cursorWidth) {
originalRect.size.width = _cursorWidth;
}else {
originalRect.size.width = 2;
}
return originalRect;
}
@end