单军华
2018-07-11 7b02207537d35bfa1714bf8beafc921f717d100a
screendisplay/Pods/HMEmoticon/????/Emoticon/HMEmoticonTextView.m
New file
@@ -0,0 +1,329 @@
//
//  HMEmoticonTextView.m
//  表情键盘
//
//  Created by 刘凡 on 16/3/3.
//  Copyright © 2016年 itcast. All rights reserved.
//
#import "HMEmoticonTextView.h"
#import "HMEmoticonAttachment.h"
#import "HMEmoticonInputView.h"
@implementation HMEmoticonTextView {
    UILabel *_placeHolderLabel;
    UILabel *_lengthTipLabel;
    NSMutableArray <NSLayoutConstraint *> *_lengthTipLabelCons;
    /// 表情输入视图
    HMEmoticonInputView *_emoticonInputView;
}
#pragma mark - 设置属性
- (BOOL)isUseEmoticonInputView {
    return self.inputView != nil;
}
- (void)setUseEmoticonInputView:(BOOL)useEmoticonInputView {
    if (self.isUseEmoticonInputView == useEmoticonInputView) {
        return;
    }
    self.inputView = (self.inputView == nil) ? _emoticonInputView : nil;
    [self reloadInputViews];
}
- (void)setPlaceholder:(NSString *)placeholder {
    _placeholder = placeholder.copy;
    _placeHolderLabel.text = _placeholder;
}
- (void)setMaxInputLength:(NSInteger)maxInputLength {
    _maxInputLength = maxInputLength;
    [self textChanged];
}
- (void)setFont:(UIFont *)font {
    _placeHolderLabel.font = font;
    [super setFont:font];
}
- (void)setText:(NSString *)text {
    [super setText:text];
    [self textChanged];
}
- (UIColor *)textColor {
    UIColor *color = [super textColor];
    return (color == nil) ? [UIColor darkGrayColor] : color;
}
- (void)setAttributedText:(NSAttributedString *)attributedText {
    [super setAttributedText:attributedText];
    [self textChanged];
}
#pragma mark - 构造函数
- (instancetype)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer {
    self = [super initWithFrame:frame textContainer:textContainer];
    if (self) {
        self.textColor = [UIColor darkGrayColor];
        self.font = [UIFont systemFontOfSize:18];
        [self prepareUI];
    }
    return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        [self prepareUI];
    }
    return self;
}
- (void)willMoveToWindow:(UIWindow *)newWindow {
    [super willMoveToWindow:newWindow];
    [self layoutIfNeeded];
}
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - 公共函数
- (NSString *)emoticonText {
    NSAttributedString *attributeText = self.attributedText;
    NSMutableString *stringM = [NSMutableString string];
    [attributeText
     enumerateAttributesInRange:
     NSMakeRange(0, attributeText.length)
     options:0
     usingBlock:^(NSDictionary<NSString *,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
         HMEmoticonAttachment *attachment = attrs[@"NSAttachment"];
         if (attachment != nil) {
             [stringM appendString:attachment.text];
         } else {
             [stringM appendString:[attributeText.string substringWithRange:range]];
         }
     }];
    return stringM.copy;
}
- (void)insertEmoticon:(HMEmoticon *)emoticon isRemoved:(BOOL)isRemoved {
    if (isRemoved) {
        [self deleteBackward];
        return;
    }
    if (emoticon.isEmoji) {
        [self replaceRange:[self selectedTextRange] withText:emoticon.emoji];
        return;
    }
    NSMutableAttributedString *attributeText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
    NSAttributedString *emoticonStr = [HMEmoticonAttachment emoticonStringWithEmoticon:emoticon font:self.font textColor:self.textColor];
    NSRange range = self.selectedRange;
    [attributeText replaceCharactersInRange:range withAttributedString:emoticonStr];
    self.attributedText = attributeText;
    self.selectedRange = NSMakeRange(range.location + 1, 0);
    [self.delegate textViewDidChange:self];
    [[NSNotificationCenter defaultCenter] postNotificationName:UITextViewTextDidChangeNotification object:self];
}
- (void)updateTipLabelBottomConstraints:(UIView *)view {
    // 判断 view 是否是当前的子视图
    if (![self.subviews containsObject:view]) {
        NSLog(@"当前仅支持相对 textView 子视图的控件参照");
        return;
    }
    [self removeConstraints:_lengthTipLabelCons];
    [_lengthTipLabelCons removeAllObjects];
    CGFloat margin = 5;
    [_lengthTipLabelCons addObject:[NSLayoutConstraint
                                    constraintWithItem:_lengthTipLabel
                                    attribute:NSLayoutAttributeTrailing
                                    relatedBy:NSLayoutRelationEqual
                                    toItem:self
                                    attribute:NSLayoutAttributeTrailing
                                    multiplier:1.0
                                    constant:-margin]];
    [_lengthTipLabelCons addObject:[NSLayoutConstraint
                                    constraintWithItem:_lengthTipLabel
                                    attribute:NSLayoutAttributeBottom
                                    relatedBy:NSLayoutRelationEqual
                                    toItem:view
                                    attribute:NSLayoutAttributeTop
                                    multiplier:1.0
                                    constant:-margin]];
    [self addConstraints:_lengthTipLabelCons];
}
#pragma mark - 监听方法
- (void)textChanged {
    _placeHolderLabel.hidden = self.hasText;
    if (_maxInputLength <= 0) {
        _lengthTipLabel.hidden = YES;
        return;
    }
    _lengthTipLabel.hidden = NO;
    NSInteger len = _maxInputLength - self.emoticonText.length;
    _lengthTipLabel.text = [NSString stringWithFormat:@"%zd", len];
    _lengthTipLabel.textColor = (len >= 0) ? [UIColor lightGrayColor] : [UIColor redColor];
}
#pragma mark - 设置界面
- (void)prepareInputView {
    __weak typeof(self) weakSelf = self;
    _emoticonInputView = [[HMEmoticonInputView alloc] initWithSelectedEmoticon:^(HMEmoticon * _Nullable emoticon, BOOL isRemoved) {
        [weakSelf insertEmoticon:emoticon isRemoved:isRemoved];
    }];
}
- (void)prepareUI {
    // 0. 准备输入视图
    [self prepareInputView];
    // 1. 注册文本变化通知
    [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(textChanged)
     name:UITextViewTextDidChangeNotification object:nil];
    // 2. 默认属性
    self.alwaysBounceVertical = YES;
    self.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
    // 3. 尺寸视图
    UIView *sizeView = [[UIView alloc] init];
    sizeView.backgroundColor = [UIColor clearColor];
    sizeView.userInteractionEnabled = NO;
    [self insertSubview:sizeView atIndex:0];
    sizeView.translatesAutoresizingMaskIntoConstraints = NO;
    [self addConstraints:[NSLayoutConstraint
                          constraintsWithVisualFormat:@"H:|-0-[sizeView]-0-|"
                          options:0
                          metrics:nil
                          views:@{@"sizeView": sizeView}]];
    [self addConstraints:[NSLayoutConstraint
                          constraintsWithVisualFormat:@"V:|-0-[sizeView]-0-|"
                          options:0
                          metrics:nil
                          views:@{@"sizeView": sizeView}]];
    [self addConstraint:[NSLayoutConstraint
                         constraintWithItem:sizeView
                         attribute:NSLayoutAttributeWidth
                         relatedBy:NSLayoutRelationEqual
                         toItem:self
                         attribute:NSLayoutAttributeWidth
                         multiplier:1.0
                         constant:0]];
    [self addConstraint:[NSLayoutConstraint
                         constraintWithItem:sizeView
                         attribute:NSLayoutAttributeHeight
                         relatedBy:NSLayoutRelationEqual
                         toItem:self
                         attribute:NSLayoutAttributeHeight
                         multiplier:1.0
                         constant:0]];
    // 4. 占位标签
    _placeHolderLabel = [[UILabel alloc] init];
    _placeHolderLabel.text = _placeholder;
    _placeHolderLabel.textColor = [UIColor lightGrayColor];
    _placeHolderLabel.font = self.font;
    _placeHolderLabel.numberOfLines = 0;
    [self addSubview:_placeHolderLabel];
    _placeHolderLabel.translatesAutoresizingMaskIntoConstraints = NO;
    CGFloat leftOffset = 5;
    CGFloat topOffset = 8;
    [self addConstraint:[NSLayoutConstraint
                         constraintWithItem:_placeHolderLabel
                         attribute:NSLayoutAttributeLeading
                         relatedBy:NSLayoutRelationEqual
                         toItem:self
                         attribute:NSLayoutAttributeLeading
                         multiplier:1.0
                         constant:leftOffset]];
    [self addConstraint:[NSLayoutConstraint
                         constraintWithItem:_placeHolderLabel
                         attribute:NSLayoutAttributeTop
                         relatedBy:NSLayoutRelationEqual
                         toItem:self
                         attribute:NSLayoutAttributeTop
                         multiplier:1.0
                         constant:topOffset]];
    [self addConstraint:[NSLayoutConstraint
                         constraintWithItem:_placeHolderLabel
                         attribute:NSLayoutAttributeWidth
                         relatedBy:NSLayoutRelationLessThanOrEqual
                         toItem:self
                         attribute:NSLayoutAttributeWidth
                         multiplier:1.0
                         constant:-2 * leftOffset]];
    // 5. 长度提示标签
    _lengthTipLabel = [[UILabel alloc] init];
    _lengthTipLabel.text = [NSString stringWithFormat:@"%zd", _maxInputLength];
    _lengthTipLabel.textColor = [UIColor lightGrayColor];
    _lengthTipLabel.font = [UIFont systemFontOfSize:12];
    [self addSubview:_lengthTipLabel];
    _lengthTipLabel.translatesAutoresizingMaskIntoConstraints = NO;
    _lengthTipLabelCons = [NSMutableArray array];
    [_lengthTipLabelCons addObject:[NSLayoutConstraint
                                    constraintWithItem:_lengthTipLabel
                                    attribute:NSLayoutAttributeTrailing
                                    relatedBy:NSLayoutRelationEqual
                                    toItem:self
                                    attribute:NSLayoutAttributeTrailing
                                    multiplier:1.0
                                    constant:-leftOffset]];
    [_lengthTipLabelCons addObject:[NSLayoutConstraint
                                    constraintWithItem:_lengthTipLabel
                                    attribute:NSLayoutAttributeBottom
                                    relatedBy:NSLayoutRelationEqual
                                    toItem:self
                                    attribute:NSLayoutAttributeBottom
                                    multiplier:1.0
                                    constant:-leftOffset]];
    [self addConstraints:_lengthTipLabelCons];
}
@end