美文网首页实用工具
iOS自动换行的输入框

iOS自动换行的输入框

作者: 缇拉亚太 | 来源:发表于2016-11-23 18:16 被阅读1438次

    由于在项目中使用自动换行输入框的场景比较多,所以就自己封了个自动换行的输入框。具体步骤,且由我一一道来。

    在苹果本身控件中,UITextView是不具备placeholder的功能,所以我们需要自己重写一下UITextView,让他具备placeholder的功能。

    效果图:

    Untitled.gif

    直接上代码:

    #import <UIKit/UIKit.h>
    
    #define SCREEN_WIDTH    ([UIScreen mainScreen].bounds.size.width)
    #define SCREEN_HEIGHT   ([UIScreen mainScreen].bounds.size.height)
    
    @interface ZXTextView : UITextView
    
    @property(nullable, nonatomic,copy) IBInspectable NSString   *placeholder;
    
    @end
    
    #import "ZXTextView.h"
    @interface ZXTextView ()
    
    -(void)refreshPlaceholder;
    
    @end
    
    @implementation ZXTextView
    {
        UILabel *placeHolderLabel;
    }
    
    @synthesize placeholder = _placeholder;
    
    -(void)initialize
    {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshPlaceholder) name:UITextViewTextDidChangeNotification object:self];
    }
    
    -(void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            
            [self initialize];
        }
        return self;
    }
    
    -(void)awakeFromNib
    {
        [super awakeFromNib];
        [self initialize];
    }
    
    -(void)refreshPlaceholder
    {
        if([[self text] length])
        {
            [placeHolderLabel setAlpha:0];
        }
        else
        {
            [placeHolderLabel setAlpha:1];
        }
        
        [self setNeedsLayout];
        [self layoutIfNeeded];
    }
    
    - (void)setText:(NSString *)text
    {
        [super setText:text];
        [self refreshPlaceholder];
    }
    
    -(void)setFont:(UIFont *)font
    {
        [super setFont:font];
        placeHolderLabel.font = self.font;
        
        [self setNeedsLayout];
        [self layoutIfNeeded];
    }
    
    -(void)layoutSubviews
    {
        [super layoutSubviews];
        
        [placeHolderLabel sizeToFit];
        placeHolderLabel.frame = CGRectMake(self.textContainerInset.left + 5,self.textContainerInset.top, CGRectGetWidth(self.frame)-16, CGRectGetHeight(placeHolderLabel.frame));
    }
    
    -(void)setPlaceholder:(NSString *)placeholder
    {
        _placeholder = placeholder;
        
        if ( placeHolderLabel == nil )
        {
            placeHolderLabel = [[UILabel alloc] init];
            placeHolderLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight);
            placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping;
            placeHolderLabel.numberOfLines = 0;
            placeHolderLabel.font = self.font;
            placeHolderLabel.backgroundColor = [UIColor clearColor];
            placeHolderLabel.textColor = [UIColor colorWithWhite:0.7 alpha:1.0];
            placeHolderLabel.alpha = 0;
            [self addSubview:placeHolderLabel];
        }
        
        placeHolderLabel.text = self.placeholder;
        [self refreshPlaceholder];
    }
    
    -(id<UITextViewDelegate>)delegate
    {
        [self refreshPlaceholder];
        return [super delegate];
    }
    
    @end
    

    接下来要做的有两件事,一为监听键盘并实时改变ZXTextView的位置,二为根据文字实时改变ZXTextView的高度。代码如下:

    #import <UIKit/UIKit.h>
    
    @class ZXTextView;
    
    @interface ZXLayoutTextView : UIView
    
    @property (weak, nonatomic) ZXTextView *textView;
    
    @property (copy, nonatomic) NSString *placeholder;
    
    @property (copy, nonatomic) void (^(sendBlock)) (ZXTextView *textView);
    
    @end
    
    #import "ZXLayoutTextView.h"
    #import "ZXTextView.h"
    #define kTextViewFont [UIFont systemFontOfSize:17]
    
    static CGFloat maxHeight = 80.0f;
    static CGFloat leftFloat = 10.0f;
    static CGFloat textViewHFloat = 36.0f;
    
    @interface ZXLayoutTextView()<UITextViewDelegate>
    @property (assign, nonatomic) CGFloat superHight;
    @property (assign, nonatomic) CGFloat textViewY;
    @property (assign, nonatomic) CGFloat keyBoardHight;
    @property (assign, nonatomic) CGRect originalFrame;
    @property (copy,nonatomic) NSString  *lastText;
    
    @end
    
    @implementation ZXLayoutTextView
    
    - (instancetype)initWithFrame:(CGRect)frame{
        self = [super initWithFrame:frame];
        if (self) {
               
            _originalFrame = frame;
            
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(keyboardWasShow:)
                                                         name:UIKeyboardWillShowNotification object:nil];
            
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(keyboardWillBeHidden:)
                                                         name:UIKeyboardWillHideNotification object:nil];
            self.backgroundColor = [UIColor whiteColor];
            
            ZXTextView *textView   = [[ZXTextView alloc] init];
            textView.delegate            = self;
            textView.placeholder         = _placeholder;
            textView.backgroundColor     = [UIColor whiteColor];
            textView.font                = kTextViewFont;
            textView.layer.cornerRadius  = 5;
            textView.layer.masksToBounds = YES;
            textView.layer.borderWidth   = 0.5;
            textView.returnKeyType       = UIReturnKeySend;
            textView.layer.borderColor   = [[UIColor grayColor] CGColor];
            textView.layoutManager.allowsNonContiguousLayout = NO;
            [self addSubview:textView];
            self.textView = textView;
    
            CGFloat textViewX = leftFloat;
            CGFloat textViewW = SCREEN_WIDTH-2*textViewX;
            CGFloat textViewH = textViewHFloat;
            CGFloat textViewY = (self.frame.size.height-textViewH)*0.5;
            
            _textView.frame = CGRectMake(textViewX, textViewY, textViewW, textViewH);
            _textViewY        = textViewY;
            _superHight       = self.frame.size.height;
            
        }
        return self;
    }
    
    - (void)layoutSubviews{
        [super layoutSubviews];
        
        self.textView.placeholder = _placeholder;
    }
    
    #pragma mark - == UITextViewDelegate
    - (void)textViewDidBeginEditing:(UITextView *)textView{
        
        self.lastText = @"";
        
        _textView.placeholder = _placeholder;
    }
    - (void)textViewDidChange:(UITextView *)textView{
    
        CGRect frame = textView.frame;
        CGSize constraintSize = CGSizeMake(frame.size.width, MAXFLOAT);
        CGSize size = [textView sizeThatFits:constraintSize];
        
        if (size.height<=frame.size.height) {
    
        }else{
            if (size.height>=maxHeight){
                size.height = maxHeight;
                textView.scrollEnabled = YES;   // 允许滚动
            }else{
                textView.scrollEnabled = NO;    // 不允许滚动
            }
        }
        textView.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, size.height);
        
        CGFloat superHeight = CGRectGetMaxY(textView.frame)+_textViewY;
        
        [UIView animateWithDuration:0 animations:^{
            [self setFrame:CGRectMake(self.frame.origin.x, SCREEN_HEIGHT-(_keyBoardHight+superHeight), self.frame.size.width, superHeight)];
        }];
    
        CGFloat h = [self heightForString:textView.text fontSize:17];
        
        if (textView.text.length >self.lastText.length+5) {
            if (h>maxHeight) {
                [textView setContentOffset:CGPointMake(0, (h-maxHeight)) animated:NO];
            }
        }
        
        self.lastText = textView.text;
    }
    
    -(float)heightForString:(NSString *)value fontSize:(float)fontSize{
        
        NSDictionary *attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:fontSize]};
        CGSize size = [value boundingRectWithSize:CGSizeMake(SCREEN_WIDTH-20, CGFLOAT_MAX) options: NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attribute context:nil].size;
        return size.height;
    }
    
    - (void)textViewDidChangeSelection:(UITextView *)textView{
    
        CGRect r = [textView caretRectForPosition:textView.selectedTextRange.end];
        CGFloat caretY =  MAX(r.origin.y - textView.frame.size.height + r.size.height + 8, 0);
        if (textView.contentOffset.y < caretY && r.origin.y != INFINITY) {
            textView.contentOffset = CGPointMake(0, caretY);
        }
    }
    
    - (void)textViewDidEndEditing:(UITextView *)textView{
        textView.scrollEnabled = NO;
        CGRect frame           = textView.frame;
        textView.frame         = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, textViewHFloat);
        [textView layoutIfNeeded];
        [_textView resignFirstResponder];
        
    }
    
    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
     replacementText:(NSString *)text {
        if ([text isEqualToString:@"\n"]){
            NSCharacterSet *whiteSpace = [NSCharacterSet whitespaceAndNewlineCharacterSet];
            NSString *str = [[NSString alloc]initWithString:[textView.text stringByTrimmingCharactersInSet:whiteSpace]];
            if (str.length != 0) {
       
                    if (_sendBlock) {
                        _sendBlock(_textView);
                        [_textView resignFirstResponder];
                        _textView.placeholder = _placeholder;
                    }
                
            }
            return NO;
        }
        return YES;
    }
    
    #pragma mark - == 键盘弹出事件
    - (void)keyboardWasShow:(NSNotification*)notification{
    
        CGRect keyBoardFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
        _keyBoardHight       = keyBoardFrame.size.height;
        
        [self translationWhenKeyboardDidShow:_keyBoardHight];
    }
    
    - (void)keyboardWillBeHidden:(NSNotification*)notification{
        
        self.textView.placeholder = _placeholder;
        [self translationWhenKeyBoardDidHidden];
    }
    
    - (void)translationWhenKeyboardDidShow:(CGFloat)keyBoardHight{
        
        [UIView animateWithDuration:0 animations:^{
            self.frame = CGRectMake(self.frame.origin.x, SCREEN_HEIGHT - (keyBoardHight+self.frame.size.height), self.frame.size.width, self.frame.size.height);
        }];
    }
    - (void)translationWhenKeyBoardDidHidden{
        
        [UIView animateWithDuration:0 animations:^{
            self.frame = _originalFrame;
        }];
    }
    
    - (void)dealloc{
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    
    @end
    

    封装完了之后,接下来就可以调用了。方法 so easy,如下:

    #import "ViewController.h"
    #import "ZXLayoutTextView.h"
    #import "ZXTextView.h"
    
    #define RGB_COLOR(r, g, b)       [UIColor colorWithRed:(r)/255.0f green:(g)/255.0f blue:(b)/255.0f alpha:1.0]
    
    @interface ViewController ()
    
    @property (nonatomic,strong) ZXLayoutTextView *commentView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        
        
        _commentView = [[ZXLayoutTextView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT-60, SCREEN_WIDTH, 60.0f)];
        _commentView.backgroundColor = RGB_COLOR(245, 245, 245);
        typeof(self) weakSelf = self;
        [_commentView setSendBlock:^(ZXTextView *textView) {
            
            weakSelf.commentView.textView.text = @"";
            
        }];
        
        [self.view addSubview:_commentView];
    }
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        
        
        self.commentView.placeholder = @"评论";
        [self.commentView.textView becomeFirstResponder];
    
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    @end
    
    

    以上就是自动换行输入框的整个创建流程,希望能对大家有用。

    相关文章

      网友评论

        本文标题:iOS自动换行的输入框

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