美文网首页
UITextView的提示文字placeHolder

UITextView的提示文字placeHolder

作者: 大鹏鸟 | 来源:发表于2017-12-06 18:33 被阅读52次

需求:

实现一个多行文本框,带有提示语。

实现:

一、思路

1、一个UILabel,添加到UITextView上
2、调整UILabel,使之能和UITextView同步
(完)

二、实现

1、坑

(1)UILabel有边距
默认label.png

因为一般的UILabel都是有边距的,所以如果直接使用,就会造成上述的错位问题,即使你及时隐藏了,肉眼会感觉到一些跳动,用户体验不好。那么怎么办呢?

方法一:添加换行

利用sizeWithAttributes:方法计算出一行的高度,然后再用方法boundingRectWithSize:options: attributes:context:计算出字符串所要占取的高度,那么视图总高度减去文本总高度,再除以一行高度就是需要添加的换行数。

方法二:垂直方向顶部对齐(不是水平左对齐)

计算出内容实际的布局和占用大小,然后稍微处理即可。
那么怎么获取内容的实际占用位置呢?查看文档接口,有这么几句话:

// override points. can adjust rect before calling super.
// label has default content mode of UIViewContentModeRedraw

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines;
- (void)drawTextInRect:(CGRect)rect;

可以在子类中通过重写下面的方法,可以调整位置。
下面是具体的实现:

@implementation ZPZLabel

- (void)setVerticalAlignment:(ZPZLabelVerticalTextAlignment)verticalAlignment {
    _verticalAlignment = verticalAlignment;
    [self setNeedsDisplay];
}

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines {
    CGRect actualRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
    switch (_verticalAlignment) {
        case ZPZLabelVerticalTextAlignmentTop:{
            actualRect.origin.y = bounds.origin.y;
        }
            break;
        case ZPZLabelVerticalTextAlignmentMiddle:{
            actualRect.origin.y = bounds.origin.y + bounds.size.height / 2 - actualRect.size.height / 2;
        }
            break;
        case ZPZLabelVerticalTextAlignmentBottom:{
            actualRect.origin.y = bounds.origin.y + bounds.size.height - actualRect.size.height;
        }
            break;
            
        default:
            break;
    }
    return actualRect;
}
//这里小心写错
- (void)drawTextInRect:(CGRect)rect {
    NSLog(@"%s",__func__);
    CGRect actualRect = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:actualRect];
    NSLog(@"%s",__func__);
}
//先调用父类的这个方法,然后是上面的方法,最后是该方法剩下的
- (void)drawRect:(CGRect)rect {
     NSLog(@"%s",__func__);
    [super drawRect:rect];
   
}

@end

这里需要注意的是不要写成了- (void)drawRect:(CGRect)rect。
具体的代码看这里

这里的实现采取第二种方法
(2)UITextView的默认字体

在iOS11下(其他的没试过),其font不存在。

2、实现

注意点:去除内边距

一般都是手动写死的,凡是写死的都会留下祸根!相信我,出来混,迟早都要还的。所以不建议写死!!!那怎么处理呢?
我们曾在这里对UITextView做了简单的探索,我们知道其内容是放在一个NSTextContainer里的,它里面的内容不是完全靠边的,所以这里除了要把UILabel里的内容调整为垂直顶部放置,UILabel的位置还要以这些做参考,代码实现如下:

- (void)adjustPlaceLabelFrame {
    UIEdgeInsets insets = self.textContainerInset;
//    NSLog(@"%@",NSStringFromUIEdgeInsets(insets));
    _placeHoldLabel.frame = CGRectMake(insets.left + self.textContainer.lineFragmentPadding, insets.top, self.frame.size.width - insets.left - insets.right - self.textContainer.lineFragmentPadding, self.frame.size.height - insets.top - insets.bottom);
    _placeHoldLabel.verticalAlignment = ZPZLabelVerticalTextAlignmentTop;
}

这里只做了简单的实现,基本使用应该是够用了,在后面的使用过程中会不断做完善!
效果如下:

效果图1.gif

至于什么条件消失和展示,相信很容易控制,代码里已经实现了!
另外,代码里将代理包装成了block,所以可以通过block直接使用了!不够的,可自行添加!

如果你有其他需求,欢迎来提,咱一起努力实现之!

相关文章

网友评论

      本文标题:UITextView的提示文字placeHolder

      本文链接:https://www.haomeiwen.com/subject/sqrlixtx.html