#import <UIKit/UIKit.h>
@interface UITextView (ZJPlaceholder)
/**
* placeholder
*/
@property (nonatomic, copy) NSString * placeholder;
/**
* placeHolder颜色
*/
@property (nonatomic, strong) UIColor * placeholderColor;
@end
#import "UITextView+ZJPlaceholder.h"
#import <objc/runtime.h>
static const void * placeHolderKey;
@interface UITextView ()
@property (nonatomic, readonly) UILabel * placeHolderLabel;
@end
@implementation UITextView (ZJPlaceholder)
+(void)load{
[super load];
method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"layoutSubviews")),
class_getInstanceMethod(self.class, @selector(zwPlaceHolder_swizzling_layoutSubviews)));
method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"dealloc")),
class_getInstanceMethod(self.class, @selector(zwPlaceHolder_swizzled_dealloc)));
method_exchangeImplementations(class_getInstanceMethod(self.class, NSSelectorFromString(@"setText:")),
class_getInstanceMethod(self.class, @selector(zwPlaceHolder_swizzled_setText:)));
}
#pragma mark - swizzled
- (void)zwPlaceHolder_swizzled_dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self zwPlaceHolder_swizzled_dealloc];
}
- (void)zwPlaceHolder_swizzling_layoutSubviews {
if (self.placeholder) {
UIEdgeInsets textContainerInset = self.textContainerInset;
CGFloat lineFragmentPadding = self.textContainer.lineFragmentPadding;
CGFloat x = lineFragmentPadding + textContainerInset.left + self.layer.borderWidth;
CGFloat y = textContainerInset.top + self.layer.borderWidth;
CGFloat width = CGRectGetWidth(self.bounds) - x - textContainerInset.right - 2*self.layer.borderWidth;
CGFloat height = [self.placeHolderLabel sizeThatFits:CGSizeMake(width, 0)].height;
self.placeHolderLabel.frame = CGRectMake(x, y, width, height);
}
[self zwPlaceHolder_swizzling_layoutSubviews];
}
- (void)zwPlaceHolder_swizzled_setText:(NSString *)text{
[self zwPlaceHolder_swizzled_setText:text];
if (self.placeholder) {
[self updatePlaceHolder];
}
}
#pragma mark - associated
-(NSString *)placeholder{
return objc_getAssociatedObject(self, &placeHolderKey);
}
-(void)setPlaceholder:(NSString *)placeholder{
objc_setAssociatedObject(self, &placeHolderKey, placeholder, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self updatePlaceHolder];
}
-(UIColor *)placeholderColor{
return self.placeHolderLabel.textColor;
}
-(void)setPlaceholderColor:(UIColor *)placeholderColor{
self.placeHolderLabel.textColor = placeholderColor;
}
#pragma mark - update
- (void)updatePlaceHolder{
if (self.text.length) {
[self.placeHolderLabel removeFromSuperview];
return;
}
self.placeHolderLabel.font = self.font?self.font:self.cacutDefaultFont;
self.placeHolderLabel.textAlignment = self.textAlignment;
self.placeHolderLabel.text = self.placeholder;
[self insertSubview:self.placeHolderLabel atIndex:0];
}
#pragma mark - lazzing
-(UILabel *)placeHolderLabel{
UILabel *placeHolderLab = objc_getAssociatedObject(self, @selector(placeHolderLabel));
if (!placeHolderLab) {
placeHolderLab = [[UILabel alloc] init];
placeHolderLab.numberOfLines = 0;
placeHolderLab.textColor = [UIColor lightGrayColor];
objc_setAssociatedObject(self, @selector(placeHolderLabel), placeHolderLab, OBJC_ASSOCIATION_RETAIN);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePlaceHolder) name:UITextViewTextDidChangeNotification object:self];
}
return placeHolderLab;
}
- (UIFont *)cacutDefaultFont{
static UIFont *font = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
UITextView *textview = [[UITextView alloc] init];
textview.text = @" ";
font = textview.font;
});
return font;
}
@end