自定义控件注意或框架注意:自己暴露在外面的属性,一定要重写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