關於UITextView的封裝

目前能夠實現的功能:

  1. 設置佔位字符,可以設置佔位字符的字體大小,字體顏色,字體高亮顏色,也可以設置屬性字符串作爲佔位字符
  2. 設置最大行數,超過最大行數之後滾動顯示
  3. 設置最多輸入的文字個數,超過之後不能輸入,並觸發block回調
  4. 設置輸入框的圓角弧度
  5. 設置光標的寬度和高度

直接上代碼:

.h文件:

//
//  KPTextView.h
//
//  使用時至少實現 佔位文字內容 和 文字的字體大小
//
//  Created by 劉鯤鵬 on 2017/5/12.
//  Copyright © 2017年 劉鯤鵬. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef void(^KP_textHeightChangedBlock)(NSString *text,CGFloat textHeight);

typedef void(^KP_textViewLengthOverLimitBlock)(NSInteger maxLengthOfText);

@interface KPTextView : UITextView


/**
 *  普通字符串 佔位文字
 */
@property (nonatomic, strong) NSString *placeholder;

/**
 *  屬性字符串 佔位文字
 */
@property (nonatomic, strong) NSAttributedString *attributedPlaceHolder;

/**
 *  佔位文字顏色,默認爲亮灰色
 */
@property (nonatomic, strong) UIColor *placeholderColor;

/**
 *  佔位文字高亮顏色,默認爲亮灰色
 */
@property (nonatomic, strong) UIColor *placeholderHighLightColor;

/**
 *  佔位符字體大小
 */
@property (nonatomic,strong) UIFont *placeholderFont;

/**
 *  textView最大行數,默認沒有高度限制
 */
@property (nonatomic, assign) NSUInteger maxNumberOfLines;

/**
 *  textView可以輸入的最大字數,默認沒有字數限制
 */
@property (nonatomic, assign) NSUInteger maxLengthOfText;

/**
 *  設置邊框寬度,默認爲1
 */
@property (nonatomic, assign) NSUInteger borderWidth;

/**
 *  設置邊框顏色,默認爲亮灰色
 */
@property (nonatomic, strong) UIColor *borderColor;

/**
 *  設置圓角,默認沒有圓角
 */
@property (nonatomic, assign) NSUInteger cornerRadius;

/**
 *  光標寬度,默認爲2
 */
@property (nonatomic, assign) NSUInteger cursorWidth;

/**
 *  光標高度,默認爲 self.font.lineHeight + 4
 */
@property (nonatomic, assign) NSUInteger cursorHeight;

/**
 *  文字高度改變會自動調用
 *  block參數(text) → 文字內容
 *  block參數(textHeight) → 文字高度
 */
@property (nonatomic, strong) KP_textHeightChangedBlock textChangedBlock;

/**
 *  文字字數超出設定值會自動調用
 *  block參數(maxLengthOfText) → 文字長度最大值
 */
@property (nonatomic, strong) KP_textViewLengthOverLimitBlock textOverLimitBlock;



- (void)textValueDidChanged:(KP_textHeightChangedBlock)block;


- (void)textLengthOverLimit:(KP_textViewLengthOverLimitBlock)block;


@end

.m文件:

//
//  KPTextView.m
//  textViewDemo
//
//  Created by 劉鯤鵬 on 2017/5/12.
//  Copyright © 2017年 劉鯤鵬. All rights reserved.
//

#import "KPTextView.h"

@interface KPTextView ()
{
    UIColor *NormalColor;
}

/**
 *  UILabel作爲placeholderView,解決佔位符問題.
 */
@property (nonatomic, weak) UILabel *placeholderView;

/**
 *  文字高度
 */
@property (nonatomic, assign) NSInteger textH;

/**
 *  文字最大高度
 */
@property (nonatomic, assign) NSInteger maxTextH;

/**
 *  textView設定的高度
 */
@property (nonatomic, assign) NSInteger textViewSettingHeight;




@end

@implementation KPTextView

- (UILabel *)placeholderView {

    if (!_placeholderView ) {
        UILabel *placeholderView = [[UILabel alloc] init];
        _placeholderView = placeholderView;
        //防止textView輸入時跳動問題
//        _placeholderView.scrollEnabled = NO;
//        _placeholderView.showsHorizontalScrollIndicator = NO;
//        _placeholderView.showsVerticalScrollIndicator = NO;
        _placeholderView.userInteractionEnabled = NO;
        _placeholderView.font = self.font;
        _placeholderView.backgroundColor = [UIColor clearColor];
        _placeholderColor = [UIColor lightGrayColor];
        _placeholderView.textColor = _placeholderColor;
        _placeholderView.numberOfLines = 0;
        _maxNumberOfLines = NSIntegerMax;
        [self addSubview:placeholderView];
    }
    return _placeholderView;
}

- (void)setMaxNumberOfLines:(NSUInteger)maxNumberOfLines {
    _maxNumberOfLines = maxNumberOfLines;

    /**
     *  根據最大的行數計算textView的最大高度
     *  計算最大高度 = (每行高度 * 總行數 + 文字上下間距)
     */
    _maxTextH = ceil(self.font.lineHeight * maxNumberOfLines + self.textContainerInset.top + self.textContainerInset.bottom);

}

- (void)setBorderWidth:(NSUInteger)borderWidth {
    _borderWidth = borderWidth;
    self.layer.borderWidth = _borderWidth;
}

- (void)setBorderColor:(UIColor *)borderColor {
    _borderColor = borderColor;
    self.layer.borderColor = _borderColor.CGColor;
}

- (void)setCornerRadius:(NSUInteger)cornerRadius {
    _cornerRadius = cornerRadius;
    self.layer.cornerRadius = cornerRadius;
}

/**
 *  通過設置placeholderColor設置私有屬性placeholderView中的textColor
 */
- (void)setPlaceholderColor:(UIColor *)placeholderColor {
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        NormalColor = placeholderColor;
    });
    _placeholderColor = placeholderColor;
    self.placeholderView.textColor = placeholderColor;
}

/**
 *  通過設置placeholder設置私有屬性placeholderView中的text
 */
- (void)setPlaceholder:(NSString *)placeholder {
    _placeholder = placeholder;
    self.placeholderView.text = placeholder;
}

/**
 *  通過設置attributedPlaceHolder設置私有屬性placeholderView中的attributedText
 */
- (void)setAttributedPlaceHolder:(NSAttributedString *)attributedPlaceHolder {
    _attributedPlaceHolder = attributedPlaceHolder;
    self.placeholderView.attributedText = attributedPlaceHolder;
}

/**
 *  通過設置_placeholderFont設置私有屬性placeholderView中的Font
 */
- (void)setPlaceholderFont:(UIFont *)placeholderFont {
    _placeholderFont = placeholderFont;
    self.placeholderView.font = placeholderFont;
    if (self.font && _placeholderFont) {

    }
}

- (void)setFont:(UIFont *)font {
    [super setFont:font];
    self.placeholderView.frame = CGRectMake(7, 8, self.bounds.size.width, font.lineHeight);
}


- (instancetype)initWithFrame:(CGRect)frame {

    if (self = [super initWithFrame:frame]) {
        [self setup];
    }
    return self;
}

- (void)setup {

    self.scrollEnabled = NO;
    self.scrollsToTop = NO;
    self.showsHorizontalScrollIndicator = NO;
    self.enablesReturnKeyAutomatically = YES;
    self.layer.borderWidth = 1;
    self.layer.borderColor = [UIColor lightGrayColor].CGColor;

    _textViewSettingHeight = self.frame.size.height;
    //實時監聽textView值得改變
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange) name:UITextViewTextDidChangeNotification object:self];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didBeginEditing) name:UITextViewTextDidBeginEditingNotification object:self];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEndEditing) name:UITextViewTextDidEndEditingNotification object:self];
}

- (void)textDidChange {

    NSInteger wordCount = self.text.length;
//    NSLog(@"%ld",(long)wordCount);
    if (_maxLengthOfText && wordCount >= _maxLengthOfText) {
        self.text = [self.text substringToIndex:_maxLengthOfText];
        if (_textOverLimitBlock) {
            _textOverLimitBlock(_maxLengthOfText);
        }
    }

    // 根據文字內容決定placeholderView是否隱藏
    self.placeholderView.hidden = self.hasText;

    NSInteger height = ceilf([self sizeThatFits:CGSizeMake(self.bounds.size.width, MAXFLOAT)].height);

    if (_textH != height) { // 高度不一樣,就改變了高度

        // 當高度大於最大高度時,需要滾動
        self.scrollEnabled = height > _maxTextH && _maxTextH > 0;

        _textH = height;

        //當不可以滾動(即 <= 最大高度)時,傳值改變textView高度
        if (_textChangedBlock && self.scrollEnabled == NO && height > _textViewSettingHeight) {
            _textChangedBlock(self.text,height);

            [self.superview layoutIfNeeded];
//            self.placeholderView.frame = self.bounds;
        }


    }
}

- (void)didBeginEditing {
    if (_placeholderHighLightColor) {
        self.placeholderColor = _placeholderHighLightColor;
    }else {
        self.placeholderColor = [UIColor lightGrayColor];
    }
}

- (void)didEndEditing {
    self.placeholderColor = NormalColor;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}



- (void)textValueDidChanged:(KP_textHeightChangedBlock)block {
    _textChangedBlock = block;
}

- (void)textLengthOverLimit:(KP_textViewLengthOverLimitBlock)block {
    _textOverLimitBlock = block;
}


- (CGRect)caretRectForPosition:(UITextPosition *)position
{
    CGRect originalRect = [super caretRectForPosition:position];

    if (_cursorHeight) {
        originalRect.size.height = _cursorHeight;
    }else {
        originalRect.size.height = self.font.lineHeight + 4;
    }
    if (_cursorWidth) {
        originalRect.size.width = _cursorWidth;
    }else {
        originalRect.size.width = 2;
    }

    return originalRect;
}

@end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章