iOS开发小技巧--自定义带有占位文字的TextView(两种方式)

自定义控件注意或框架注意:自己暴露在外面的属性,一定要重写setter,保证外界与内部的交互性

一.方案一:通过drawRect:方法将文字画到textView中,监听文字改变用的是通知中心(代理也可以监听文字改变,但是这种方式就成了自己作为自己的代理了,不推荐这种方法)发出的消息

UITextViewTextDidChangeNotification.自己监听通知.

  • 对外界提供两个属性

  • 内部实现
 1 #import "ChaosPlaceholdTextView.h"
 2 
 3 @implementation ChaosPlaceholdTextView
 4 
 5 - (instancetype)initWithFrame:(CGRect)frame
 6 {
 7     if (self = [super initWithFrame:frame]) {
 8         
 9         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextViewTextDidChangeNotification object:nil];
10         
11         // 外界文字颜色不设置,默认为灰色
12         self.placeholdColor = [UIColor grayColor];
13     }
14     return self;
15 }
16 
17 - (void)dealloc
18 {
19     [[NSNotificationCenter defaultCenter] removeObserver:self];
20 }
21 
22 - (void)textChange
23 {
24     [self setNeedsDisplay];
25 }
26 
27 // 调用drawRect时,会将之前的图像擦除掉,重新绘制
28 - (void)drawRect:(CGRect)rect {
29     
30     if ([self hasText]) return;
31     
32     rect.origin.y += (64 + 7);
33     rect.origin.x += 5;
34     rect.size.width -= 2 * rect.origin.x;
35     
36     NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
37     attrs[NSForegroundColorAttributeName] = self.placeholdColor;
38     attrs[NSFontAttributeName] = [UIFont systemFontOfSize:17];
39     [self.placehold drawInRect:rect withAttributes:attrs];
40 }
41 
42 // 设计框架需注意,给外界提供了属性后,一定重写出行的setter,这样既可以时时监听使用者对属性的更改,还可以跟好的与外界代码进行交互
43 - (void)setPlacehold:(NSString *)placehold
44 {
45     _placehold = placehold;
46     // 设置了站位文字后,需要重绘一遍
47     [self setNeedsDisplay];
48 }
49 
50 - (void)setPlaceholdColor:(UIColor *)placeholdColor
51 {
52     _placeholdColor = placeholdColor;
53     [self setNeedsDisplay];
54 }
55 
56 // 同时,也要考虑到
57 - (void)setFont:(UIFont *)font
58 {
59     [super setFont:font];
60     
61     [self setNeedsDisplay];
62 }
63 
64 - (void)setText:(NSString *)text
65 {
66     [super setText:text];
67     
68     [self setNeedsDisplay];
69 }
70 
71 - (void)setAttributedText:(NSAttributedString *)attributedText
72 {
73     [super setAttributedText:attributedText];
74     
75     [self setNeedsDisplay];
76 }
77 
78 @end
  • 缺点:由于是画上去的,当设置了textView的alwaysBounceHorizontal属性后,不能跟随着scrollView的滑动而滑动,如下图

方案二:通过给TextView添加一个Label,也是通过监听文字改变的通知,修改label的hidden属性.

  1 #import "ChaosPlaceholdTextView.h"
  2 
  3 @interface ChaosPlaceholdTextView()
  4 /** 占位文字label */
  5 @property (nonatomic, weak) UILabel *placeholderLabel;
  6 @end
  7 
  8 @implementation ChaosPlaceholdTextView
  9 
 10 - (UILabel *)placeholderLabel
 11 {
 12     if (!_placeholderLabel) {
 13         // 添加一个用来显示占位文字的label
 14         UILabel *placeholderLabel = [[UILabel alloc] init];
 15         placeholderLabel.numberOfLines = 0;
 16         placeholderLabel.x = 4;
 17         placeholderLabel.y = 7;
 18         [self addSubview:placeholderLabel];
 19         _placeholderLabel = placeholderLabel;
 20     }
 21     return _placeholderLabel;
 22 }
 23 
 24 - (instancetype)initWithFrame:(CGRect)frame
 25 {
 26     if (self = [super initWithFrame:frame]) {
 27         // 垂直方向上永远有弹簧效果
 28         self.alwaysBounceVertical = YES;
 29         
 30         // 默认字体
 31         self.font = [UIFont systemFontOfSize:15];
 32         
 33         // 默认的占位文字颜色
 34         self.placeholderColor = [UIColor grayColor];
 35         
 36         // 监听文字改变
 37         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange) name:UITextViewTextDidChangeNotification object:nil];
 38     }
 39     return self;
 40 }
 41 
 42 - (void)dealloc
 43 {
 44     [[NSNotificationCenter defaultCenter] removeObserver:self];
 45 }
 46 
 47 /**
 48  * 监听文字改变
 49  */
 50 - (void)textDidChange
 51 {
 52     // 只要有文字, 就隐藏占位文字label
 53     self.placeholderLabel.hidden = self.hasText;
 54 }
 55 
 56 /**
 57  * 更新占位文字的尺寸
 58  */
 59 - (void)updatePlaceholderLabelSize
 60 {
 61     CGSize maxSize = CGSizeMake(ChaosScreenW - 2 * self.placeholderLabel.x, MAXFLOAT);
 62     self.placeholderLabel.size = [self.placeholder boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : self.font} context:nil].size;
 63 }
 64 
 65 #pragma mark - 重写setter
 66 - (void)setPlaceholderColor:(UIColor *)placeholderColor
 67 {
 68     _placeholderColor = placeholderColor;
 69     
 70     self.placeholderLabel.textColor = placeholderColor;
 71 }
 72 
 73 - (void)setPlaceholder:(NSString *)placeholder
 74 {
 75     _placeholder = [placeholder copy];
 76     
 77     self.placeholderLabel.text = placeholder;
 78     
 79     [self updatePlaceholderLabelSize];
 80 }
 81 
 82 - (void)setFont:(UIFont *)font
 83 {
 84     [super setFont:font];
 85     
 86     self.placeholderLabel.font = font;
 87     
 88     [self updatePlaceholderLabelSize];
 89 }
 90 
 91 - (void)setText:(NSString *)text
 92 {
 93     [super setText:text];
 94     
 95     [self textDidChange];
 96 }
 97 
 98 - (void)setAttributedText:(NSAttributedString *)attributedText
 99 {
100     [super setAttributedText:attributedText];
101     
102     [self textDidChange];
103 }
104 
105 @end

 

原文地址:https://www.cnblogs.com/gchlcc/p/5542774.html