1、自定义placeholder样式
static char *labelKey = "placeholderKey";
static char *needAdjust = "needAdjust";
static char *changeLocation = "location";
//添加placeholdLabel属性
@property(nonatomic,readonly) UILabel *placeholdLabel;
/** placeholder */
@property(nonatomic, copy, nullable) NSString *placeholder;
/** placeholder颜色 */
@property(nonatomic,copy) UIColor *placeholderColor;
/** 富文本 */
@property(nonatomic,strong, nullable) NSAttributedString *attributePlaceholder;
/** 位置 */
@property(nonatomic,assign) CGPoint placeholderLocation;
+ (void)load {
method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"dealloc") ), class_getInstanceMethod(self.class, NSSelectorFromString(@"swizzledDealloc")));
method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"layoutSubviews") ), class_getInstanceMethod(self.class, NSSelectorFromString(@"swizzledLayoutSubviews")));
}
- (void)swizzledDealloc {
// 移除观察
[self removeObserver:self forKeyPath:@"font"];
[self removeObserver:self forKeyPath:@"text"];
//移除监听
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self swizzledDealloc];
}
- (void)swizzledLayoutSubviews {
[self swizzledLayoutSubviews];
[self updateLabel];
}
#pragma mark - 是否需要调整字体
- (BOOL)needAdjustFont {
return [objc_getAssociatedObject(self, needAdjust) boolValue];
}
- (void)setNeedAdjustFont:(BOOL)needAdjustFont {
objc_setAssociatedObject(self, needAdjust, @(needAdjustFont), OBJC_ASSOCIATION_ASSIGN);
}
#pragma mark - observer font KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"font"]) {
self.needAdjustFont = YES;
[self updateLabel];
} else if ([keyPath isEqualToString:@"text"]) {
[self updateLabel];
}
}
- (UILabel *)placeholdLabel {
UILabel *label = objc_getAssociatedObject(self, labelKey);
if (!label) {
label = [[UILabel alloc] init];
label.textAlignment = NSTextAlignmentLeft;
label.numberOfLines = 0;
label.font = self.font;
label.textColor = [self.class defaultColor];
objc_setAssociatedObject(self, labelKey, label, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
//添加通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateLabel) name:UITextViewTextDidChangeNotification object:nil];
//监听font的变化
[self addObserver:self forKeyPath:@"font" options:NSKeyValueObservingOptionNew context:nil];
[self addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:nil];
}
return label;
}
+ (UIColor *)defaultColor {
static UIColor *color = nil;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (@available(iOS 13.0, *)) {
color = UIColor.placeholderTextColor;
} else {
UITextField *textField = [[UITextField alloc] init];
textField.placeholder = @" ";
color = [textField valueForKeyPath:@"_placeholderLabel.textColor"];
}
});
return color;
}
- (void)updateLabel {
if (self.text.length) {
[self.placeholdLabel removeFromSuperview];
return;
}
//显示label
[self insertSubview:self.placeholdLabel atIndex:0];
// 是否需要更新字体(NO 采用默认字体大小)
if (self.needAdjustFont) {
self.placeholdLabel.font = self.font;
self.needAdjustFont = NO;
}
CGFloat lineFragmentPadding = self.textContainer.lineFragmentPadding; //边距
UIEdgeInsets contentInset = self.textContainerInset;
//设置label frame
CGFloat labelX = lineFragmentPadding + contentInset.left;
CGFloat labelY = contentInset.top;
if (self.placeholderLocation.x != 0 || self.placeholderLocation.y != 0) {
if (self.placeholderLocation.x < 0 || self.placeholderLocation.x > CGRectGetWidth(self.bounds) - lineFragmentPadding - contentInset.right || self.placeholderLocation.y< 0) {
// 不做处理
}else{
labelX += self.placeholderLocation.x;
labelY += self.placeholderLocation.y;
}
}
CGFloat labelW = CGRectGetWidth(self.bounds) - contentInset.right - labelX;
CGFloat labelH = [self.placeholdLabel sizeThatFits:CGSizeMake(labelW, MAXFLOAT)].height;
self.placeholdLabel.frame = CGRectMake(labelX, labelY, labelW, labelH);
}
@end
@implementation UITextView (placeholder)
- (void)setPlaceholder:(NSString *)placeholder {
self.placeholdLabel.text = placeholder;
[self updateLabel];
}
- (NSString *)placeholder {
return self.placeholdLabel.text;
}
- (void)setPlaceholderColor:(UIColor *)placeholderColor {
self.placeholdLabel.textColor = placeholderColor;
[self updateLabel];
}
- (UIColor *)placeholderColor {
return self.placeholdLabel.textColor;
}
- (void)setAttributePlaceholder:(NSAttributedString *)attributePlaceholder {
self.placeholdLabel.attributedText = attributePlaceholder;
[self updateLabel];
}
- (NSAttributedString *)attributePlaceholder {
return self.placeholdLabel.attributedText;
}
- (void)setPlaceholderLocation:(CGPoint)placeholderLocation {
objc_setAssociatedObject(self, changeLocation,NSStringFromCGPoint(placeholderLocation), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self updateLabel];
}
- (CGPoint)placeholderLocation {
return CGPointFromString(objc_getAssociatedObject(self, changeLocation));
}