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