TextView占位符,随着字符串长度自动增高

2017-09-09  本文已影响0人  tangbin583085

开发这个控件的缘由是因为目前做的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;


上一篇下一篇

猜你喜欢

热点阅读