开发这个控件的缘由是因为目前做的App有一个对话框的功能,而苹果提供的原生UITextField或者UITextView不符合对话框的需求(该控件可用于对话输入框)。
限制
1,UITextFiled不能多行输入
2,UITextView没有占位符
3,2者都不能自动增高功能。
重写UITextView
1,为UITextView添加占位符
- (UITextView *)placeHolder {
if (_placeHolder == nil) {
UITextView *placeHolder = [[UITextView alloc] init];
_placeHolder = placeHolder;
placeHolder.userInteractionEnabled = NO;
placeHolder.showsVerticalScrollIndicator = NO;
placeHolder.showsHorizontalScrollIndicator = NO;
placeHolder.scrollEnabled = NO;
placeHolder.font = self.font;
placeHolder.backgroundColor= [UIColor clearColor];
placeHolder.textColor = [UIColor lightGrayColor];
[self addSubview:placeHolder];
}
return _placeHolder;
}
监听文本变化显示或隐藏占位符
- (instancetype)init {
if (self = [super init]) {
// 添加文本变化通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeText:) name:UITextViewTextDidChangeNotification object:nil];
}
return self;
}
2,处理文本变化
自定义方法 didChangeText,比如显示隐藏站位文本,根据字符串计算最新高度
- (void)didChangeText:(NSNotification *)notification{
// 隐藏显示占位符
self.scrollEnabled = self.placeHolder.hidden = self.hasText;
// 以防监听到非自己的文本变化
TBTextView *textView = notification.object;
if (textView == nil || textView != self || !self.tbDelegate || ![self.tbDelegate respondsToSelector:@selector(changeHeight:textString:textView:)]) return;
// 计算宽高
CGFloat height = [self.text boundingRectWithSize:CGSizeMake(self.frame.size.width - 10, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : self.font} context:nil].size.height + 0.5;// 加0.5以防显示不全 -10是因为输入框左右有边距
// 记录初始化高度
static BOOL firstTimeIn = YES;
if (firstTimeIn) {
firstTimeIn = NO;
_initHeight = self.bounds.size.height;
}
// 为什么取整? 因为有晃动的情况出现
NSInteger heigtInt = ceil(height);
CGFloat curHeight = heigtInt + self.textContainerInset.top + self.textContainerInset.bottom;
// 当前高度比原始高度小
if (_initHeight > curHeight) {
curHeight = _initHeight;
}
// 不能超过最大高度
if (_maxLine > 0 && curHeight > _maxHeight ) {
curHeight = _maxHeight;
self.scrollEnabled = YES;
}else{
self.scrollEnabled = NO;
}
// 执行代理
if ([self.tbDelegate respondsToSelector:@selector(changeHeight:textString:textView:)]) {
[self.tbDelegate changeHeight:curHeight textString:textView.text textView:textView];
}
}
3,代理返回新高度
// 执行代理
if ([self.tbDelegate respondsToSelector:@selector(changeHeight:textString:textView:)]) {
[self.tbDelegate changeHeight:curHeight textString:textView.text textView:textView];
}
有些小细节需要注意下:
1,为什么用 UITextView 作占位符而不用UILabel,是因为UITextView可以与本身文字可以重叠一致
2,UITextView的上下有textContainerInset
3, 为什么取整? 因为有抖动的情况出现
NSInteger heigtInt = ceil(height);
CGFloat curHeight = heigtInt + self.textContainerInset.top + self.textContainerInset.bottom;