美文网首页iOS学习笔记OS寒哥管理的技术专题iOS
手把手教你如何给TextView添加placehold

手把手教你如何给TextView添加placehold

作者: _李布斯 | 来源:发表于2015-05-24 11:50 被阅读32883次
    gif

    UITextField 有个系统自带的文本提示文字也就是placeholder属性,大家应该都知道,最常见的就用在搜索框上面的提醒文字。但是UITextField因为只能输入一行文字的原因,可能有时候不能满足我们的需求,这时候 UITextView 这个控件就派到用场了。但是UITextView虽然支持输入多行文字,却没有像 UITextField那样有个placeholder属性给我们调用,本文就是教大家如何给  UITextView 增加一个 placeholder属性。废话不多少,我们开始:

    虽然这个号早就不维护了,但是好多人有问题,所有又跑上来更新下!

    时光飞逝啊,当初写下这篇文章的日子是 `2015.05.24 11:50`,想想现在自己还在 iOS 开发这条路上辛苦的爬着,废话不多说,有兴趣的去看看下面这个地址的 demo 吧:

    https://github.com/ifelseboyxx/XXTextView




    UITextField 有个系统自带的文本提示文字也就是placeholder属性,大家应该都知道,最常见的就用在搜索框上面的提醒文字。但是UITextField因为只能输入一行文字的原因,可能有时候不能满足我们的需求,这时候 UITextView 这个控件就派到用场了。但是UITextView虽然支持输入多行文字,却没有像 UITextField那样有个placeholder属性给我们调用,本文就是教大家如何给  UITextView 增加一个 placeholder属性。废话不多少,我们开始:

    (一)我们先新建一个继承自 UITextView 的 自定义控件 JSTextView。

      (二)  然后在 - (instancetype)initWithFrame:(CGRect)frame 的里面初始化一个 UILabel。没错,我的思路就是用一个 UILabel 来实现 placeholder 效果。具体代码如下:

    JSTextView.h 文件

    这里我们暴露出 一个文字和文字颜色属性,能够方便我们使用的时候设置这些属性!


    #import <UIKit/UIKit.h>

    @interface JSTextView :UITextView

    @property(nonatomic,copy) NSString *myPlaceholder;  //文字

    @property(nonatomic,strong) UIColor *myPlaceholderColor; //文字颜色

    @end

    JSTextView.m 文件

    #import"JSTextView.h"

    @interface JSTextView()

    @property (nonatomic,weak) UILabel *placeholderLabel; //这里先拿出这个label以方便我们后面的使用

    @end

    - (instancetype)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame]; 

    if(self) {

    self.backgroundColor= [UIColor clearColor];

    UILabel *placeholderLabel = [[UILabel alloc]init];//添加一个占位label

    placeholderLabel.backgroundColor= [UIColor clearColor];

    placeholderLabel.numberOfLines=0; //设置可以输入多行文字时可以自动换行

    [self addSubview:placeholderLabel];

    self.placeholderLabel= placeholderLabel; //赋值保存

    self.myPlaceholderColor= [UIColor lightGrayColor]; //设置占位文字默认颜色

    self.font= [UIFont systemFontOfSize:15]; //设置默认的字体

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange) name:UITextViewTextDidChangeNotification object:self]; //通知:监听文字的改变

    }

    return self;

    }

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange) name:UITextViewTextDidChangeNotification object:self]; //通知:监听文字的改变

    这里我来解释下: 这个UITextViewTextDidChangeNotification通知会监听UITextView文字的改变,也就是说只要文字一改变就会调用这个通知的方法,利用这个我们可以控制  我们刚才在- (instancetype)initWithFrame:(CGRect)frame  方法里面初始化的  UILabel 的显示和隐藏:

    #pragma mark -监听文字改变

    - (void)textDidChange {

    self.placeholderLabel.hidden = self.hasText;

    }

    这个 hasText  是一个 系统的 BOOL  属性,如果 UITextView 输入了文字  hasText 就是 YES,反之就为 NO。

    (三)我们在  - (void)layoutSubviews 方法里面设置 UILabel 的 frame.

    - (void)layoutSubviews {

    [super layoutSubviews];

    self.placeholderLabel.y=8; //设置UILabel 的 y值

    self.placeholderLabel.x=5;//设置 UILabel 的 x 值

    self.placeholderLabel.width=self.width-self.placeholderLabel.x*2.0; //设置 UILabel 的 x

    //根据文字计算高度

    CGSize maxSize =CGSizeMake(self.placeholderLabel.width,MAXFLOAT);

    self.placeholderLabel.height= [self.myPlaceholder boundingRectWithSize:maxSize options:NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : self.placeholderLabel.font} context:nil].size.height;

    :- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary*)attributes context:(NSStringDrawingContext*)contextNS_AVAILABLE_IOS(7_0); 这个方法我来解释下:

    以前我们想要获得 UILabel 文字的大小都用的下图的一系列接口:

    但是 这些方法已经被苹果遗弃了,并且出现了新的方法,也就是上面的那个方法。

    图1

    (1)size参数: 宽高限制,用于计算文本绘制时占据的矩形块 。

    (2)options参数: NSStringDrawingOptions 大家可以看看这个 官方介绍。在多行的情况下 至少要包含 NSStringDrawingUsesLineFragmentOrigin NSStringDrawingUsesFontLeading  这两个属性。

      (3) attributes参数: 这是个字典  @{NSFontAttributeName : self.placeholderLabel.font}  这里注意要成对的传。

    (4)context参数 : 可以为 nil


    (四)  重写我们 暴露出来的 文字 ,颜色以及系统的font 的 set方法 :

    - (void)setMyPlaceholder:(NSString*)myPlaceholder{

    _myPlaceholder= [myPlaceholder copy];

    //设置文字

    self.placeholderLabel.text= myPlaceholder;

    //重新计算子控件frame

    [self setNeedsLayout];

    }

    - (void)setMyPlaceholderColor:(UIColor*)myPlaceholderColor{

    _myPlaceholderColor= myPlaceholderColor;

    //设置颜色

    self.placeholderLabel.textColor= myPlaceholderColor;

    }

    //重写这个set方法保持font一致

    - (void)setFont:(UIFont*)font {

    [super setFont:font];

    self.placeholderLabel.font= font;

    //重新计算子控件frame

    [self setNeedsLayout];

    }

    (五) 重写 - (void)setText:(NSString*)text  以及 - (void)setAttributedText:(NSAttributedString*)attributedText 方法来控制 UILabel 的显示 和 隐藏

    - (void)setText:(NSString*)text{

    [super setText:text];

    [self textDidChange]; //这里调用的就是 UITextViewTextDidChangeNotification 通知的回调

    - (void)setAttributedText:(NSAttributedString*)attributedText {

    [super setAttributedText:attributedText];

    [self textDidChange]; //这里调用的就是UITextViewTextDidChangeNotification 通知的回调

    }

    (六) 最后别忘了销毁 通知

    - (void)dealloc{

    [[NSNotificationCenter defaultCenter]removeObserver:UITextViewTextDidChangeNotification];

    }

    (7) 如何使用 

    - (void)setUpTextView {

    JSTextView *textView = [[JSTextView alloc]initWithFrame:self.view.bounds];

    [self.view addSubview:textView];

    //1.设置提醒文字

    textView.myPlaceholder=@"分享新鲜事...";

    //2.设置提醒文字颜色

    textView.myPlaceholderColor= [UIColorlightGrayColor];

    相关文章

      网友评论

      • 吃蘑菇De大灰狼:直接添加通知就行,文字改变的时候,检查UITextView的字符串长度,有就显示Placeholder~
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshPlaceholder) name:UITextViewTextDidChangeNotification object:self];
      • 浮动跳跃:你这个看起来好高大上。
        不过分享我的一个方法。
        直接给textView 加一个子label,然后根据textView的内容>0隐藏lab,else 显示lab:smirk:
      • 西门吸雪:你这个通知,,使用的是不是太浪费了,,,
      • yaya_pangdun:你的格式有点乱啊,完全没有体现markdown的好处。
      • Rchongg:drawrect
      • bd15fc24ecdb:self.placeholderLabel.y=8;加到项目里面报错啊 哥们
        嘿_黑羊:你好,请问你明白这句代码是怎么来的了吗?可以解释一下吗?
      • defef388b4fa:求这个demo,,18236592737@163.com,,谢谢你..
      • 笔寂晓才:写的不错,简洁明了
      • 7b77e6e820c6:self.placeholderLabel.y=8; //设置UILabel 的 y值????不是 self.placeholderLabel.frame.origin.y?
        0x00chen:@大王派我来巡山嘞 815807765@qq.com 谢谢 :smile:
        7b77e6e820c6:@㴴禕斨 给我邮箱,我发你封装好的代码吧
        0x00chen:@大王派我来巡山嘞 self.placeholderLabel.frame.origin.y我打这个报错了,你解决了吗?
      • 旧时光如昨:为什么我书写了文字之后再删除,placeholder的提示语就不会再出现了??
        08928d558a60:@旧时光如昨 在textView.text 判断是否为空 加个判断
      • 施主小欣:placeholderLabel的x和y的5,8是怎么得出来的? 有工程可以参考下吗?807555206@qq.com 谢谢!
        fc97cee75c27:这里的8是从textContainerInset来的,textContainerInset的默认值是(8,0,8,0)所以这里用了8,5是为了让placeholder两边留一点空隙而不是贴着textview的边。不过这样实现是有问题的。如果textContainerInset被改了的话,placeholder和输入的文本的位置就会不一样。
        嘿_黑羊:@alamZheng 你好,请问为什么self.placeholderLable有x属性?可以解释下为什么有self.placeholderLabel.x这句吗?
        alamZheng:@施主小欣 你可以设置placeholderLabel的背景图片看看,如果X和Y都是0,贴着textView不好看
      • YwWyW:placeholderLabel的x和y的5,8是怎么得出来的?这个值在6plus下面没问题,在其他2x手机下面的话label就和光标错位了。。
        fc97cee75c27:这里的8是从textContainerInset来的,textContainerInset的默认值是(8,0,8,0)所以这里用了8,5是为了让placeholder两边留一点空隙而不是贴着textview的边。不过这样实现是有问题的。如果textContainerInset被改了的话,placeholder和输入的文本的位置就会不一样。
        Snail_cz:@YwWyW 坐标问题,个人觉得可以用屏幕的比例来做,这样可以使用于不同的手机
      • _李布斯:@南栀倾寒 对啊,最近在学习他的视频,整理下这个知识点
        0e794f621839:@_李布斯 求视频地址
      • 南栀倾寒:mj讲的新浪微博
        醉叶惜秋:@南栀倾寒 请问你有这个新浪微博的视频嘛, 求分享,谢谢

      本文标题: 手把手教你如何给TextView添加placehold

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