自定义控件注意或框架注意:自己暴露在外面的属性,一定要重写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)dealloc18 {19 [[NSNotificationCenter defaultCenter] removeObserver:self];20 }21 22 - (void)textChange23 {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 *)placehold44 {45 _placehold = placehold;46 // 设置了站位文字后,需要重绘一遍47 [self setNeedsDisplay];48 }49 50 - (void)setPlaceholdColor:(UIColor *)placeholdColor51 {52 _placeholdColor = placeholdColor;53 [self setNeedsDisplay];54 }55 56 // 同时,也要考虑到57 - (void)setFont:(UIFont *)font58 {59 [super setFont:font];60 61 [self setNeedsDisplay];62 }63 64 - (void)setText:(NSString *)text65 {66 [super setText:text];67 68 [self setNeedsDisplay];69 }70 71 - (void)setAttributedText:(NSAttributedString *)attributedText72 {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