美文网首页
带有placeholder的自定义textview

带有placeholder的自定义textview

作者: Sh1mmer | 来源:发表于2019-07-05 15:30 被阅读0次

思路是将一个label作为placeholder放在textview上
textview添加观察者来观察textview的text变化 通过textview的 text变化来修改作为placeholder的label

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface UIPlaceHolderTV : UITextView
/**
 占位符
 */
@property (nonatomic, strong) NSString *placeholder;
/**
 占位符颜色
 */
@property (nonatomic, strong) UIColor *placeholderColor;
/**
 文字改变

 @param notification 通知
 */
-(void)textChanged:(NSNotification*)notification;
/**
 初始化方法

 @param frame frame
 @param adaption 是否自动适应大小
 @return self
 */
- (id)initWithFrame:(CGRect)frame adaption:(BOOL)adaption;
@property (nonatomic, strong) UILabel *placeHolderLabel;
@end
#import "UIPlaceHolderTV.h"
@interface UIPlaceHolderTV()<UITextViewDelegate>

@end
@implementation UIPlaceHolderTV
CGFloat const UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION = 0.25;
- (void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

- (void)awakeFromNib{
    [super awakeFromNib];
    
    if (!self.placeholder) {
        _placeholder = @"";
    }
    
    if (!self.placeholderColor) {
        [self setPlaceholderColor:[UIColor colorWithRed:203/255.0 green:203/255.0 blue:203/255.0 alpha:1]];
    }
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}

- (id)initWithFrame:(CGRect)frame adaption:(BOOL)adaption {
    if( (self = [super initWithFrame:frame]) ){
        _placeholder = @"";
        [self setPlaceholderColor:[UIColor colorWithRed:203/255.0 green:203/255.0 blue:203/255.0 alpha:1]];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
        if (adaption) {
            
            self.delegate = self;
        }
    }
    return self;
}

- (void)textChanged:(NSNotification *)notification {
    if([[self placeholder] length] == 0){
        return;
    }
    
    [UIView animateWithDuration:UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION animations:^{
        if([[self text] length] == 0)
        {
            [[self viewWithTag:999] setAlpha:1];
        }
        else
        {
            [[self viewWithTag:999] setAlpha:0];
        }
    }];
}

- (void)setText:(NSString *)text {
    [super setText:text];
    [self textChanged:nil];
}

- (void)drawRect:(CGRect)rect{
    if( [[self placeholder] length] > 0 ){
        UIEdgeInsets insets = self.textContainerInset;
        _placeHolderLabel.text = self.placeholder;
        [_placeHolderLabel sizeToFit];
        [_placeHolderLabel setFrame:CGRectMake(insets.left+5,insets.top,self.bounds.size.width - (insets.left +insets.right+10),CGRectGetHeight(_placeHolderLabel.frame))];
        [self sendSubviewToBack:_placeHolderLabel];
    }
    
    if( [[self text] length] == 0 && [[self placeholder] length] > 0 ){
        [[self viewWithTag:999] setAlpha:1];
    }
    
    [super drawRect:rect];
}
- (void)setPlaceholder:(NSString *)placeholder{
    if (_placeholder != placeholder) {
        _placeholder = placeholder;
        [self setNeedsDisplay];
        UIEdgeInsets insets = self.textContainerInset;
        if (_placeHolderLabel == nil )
        {
            
            _placeHolderLabel = [[UILabel alloc] initWithFrame:CGRectMake(insets.left+5,insets.top,self.bounds.size.width - (insets.left +insets.right+10),1.0)];
            _placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping;
            _placeHolderLabel.font = self.font;
            _placeHolderLabel.backgroundColor = [UIColor clearColor];
            _placeHolderLabel.textColor = self.placeholderColor;
            
            _placeHolderLabel.alpha = 0;
            _placeHolderLabel.tag = 999;
            [self addSubview:_placeHolderLabel];
        }
    }
    
}

//计算输入文字高度的方法,之所以返回的高度值加22是因为UITextView有一个初始的高度值40,但是输入第一行文字的时候文字高度只有18,所以UITextView的高度会发生变化,效果不太好

- (float) heightForTextView: (UITextView *)textView WithText: (NSString *) strText{
    CGSize constraint = CGSizeMake(textView.contentSize.width , CGFLOAT_MAX);
    CGRect size = [strText boundingRectWithSize:constraint options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                                     attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14]}
                                        context:nil];
    float textHeight = size.size.height + 22.0;
    return textHeight;
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    CGRect frame = textView.frame;
    float height;
    if ([text isEqual:@""]) {
        if (![textView.text isEqualToString:@""]) {
            height = [ self heightForTextView:textView WithText:[textView.text substringToIndex:[textView.text length] - 1]];
        }else{
            height = [ self heightForTextView:textView WithText:textView.text];
        }
    }else{
        
        height = [self heightForTextView:textView WithText:[NSString stringWithFormat:@"%@%@",textView.text,text]];
    }
    
    frame.size.height = height;
    [UIView animateWithDuration:0.5 animations:^{
        
        textView.frame = frame;
        
    } completion:nil];
    
    return YES;
}
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    UIMenuController *menuController = [UIMenuController sharedMenuController];
    if (menuController) {
        [UIMenuController sharedMenuController].menuVisible = NO;
    }
    return NO;
}

- (BOOL)canBecomeFirstResponder
{
    return self.editable;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end

相关文章

网友评论

      本文标题:带有placeholder的自定义textview

      本文链接:https://www.haomeiwen.com/subject/nbrehctx.html