iOS UITextView 常用 Category(类目)分享

西门桃桃 2020-08-01 PM 1484℃ 0条

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));
}

非特殊说明,本博所有文章均为博主原创。

评论啦~