首页 > 代码库 > 新浪微博客户端(58)-处理点击微博内容中的关键字

新浪微博客户端(58)-处理点击微博内容中的关键字

 

DJStatus.m

// 创建一个用于包含特殊文本的集合
    NSMutableArray *specialTextArray = [NSMutableArray array];
    
    
    // 取出数组中的文本块进行拼接
    for (DJStatusPart *part in statusParts) {
     
        NSAttributedString *subString = nil;
        if (part.isSpecial) { // 判断是否是特殊文本(若是特殊文本,则进行特殊处理,超链接:变色,表情文本:更换成表情图片)
            if (part.isEmotion) { //【Emotion表情】
                
                DJEmotion *emotion = [DJEmotionTool emotionWithChs:part.text];
                if (emotion) { // 找到了当前文本对应的Emotion表情
                    NSString *emotionName = emotion.png;
                    NSString *imageName = nil;
                    
                    if ([emotionName hasPrefix:@"d_"] || [emotionName hasPrefix:@"f_"] ||
                        [emotionName hasPrefix:@"h_"] || [emotionName hasPrefix:@"l_"] || [emotionName hasPrefix:@"o_"] || [emotionName hasPrefix:@"w_"]) { // 默认表情
                        imageName = [NSString stringWithFormat:@"EmotionIcons/default/%@",emotion.png];
                    } else if ([emotionName hasPrefix:@"lxh_"]) { // 浪小花表情
                        imageName = [NSString stringWithFormat:@"EmotionIcons/lxh/%@",emotion.png];
                    }
                    
                    NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
                    attachment.image = [UIImage imageNamed:imageName];
                    attachment.bounds = CGRectMake(0, -4, 16, 16);
                    subString = [NSAttributedString attributedStringWithAttachment:attachment];

                } else {
                    // 未在plist列表中找到对应表情,或该表情为Emoji
                    subString = [[NSAttributedString alloc] initWithString:part.text];
                }
                
            } else { // 【超链接&昵称】将字体颜色修改为DJColor(82,118,169)
                subString = [[NSAttributedString alloc] initWithString:part.text attributes:@{NSForegroundColorAttributeName : DJColor(82, 118, 169)}];
                
                // 保存非表情的特殊文字
                NSUInteger location = attributedText.length;
                NSUInteger length = part.text.length;
                DJSpecialText *specialText = [[DJSpecialText alloc] init];
                specialText.text = part.text;
                specialText.range = NSMakeRange(location, length);
                [specialTextArray addObject:specialText];
                
            }
        } else { // 【普通文本】不做任何处理
            subString = [[NSAttributedString alloc] initWithString:part.text];
        }

        [attributedText appendAttributedString:subString];
    }
    
    
    // 将保存有特殊文本的集合添加到DJStatus的属性上
    [attributedText addAttribute:@"special" value:specialTextArray range:NSMakeRange(0, 1)];

 

DJStatusTextView.m

#import "DJStatusTextView.h"
#import "DJSpecialText.h"


#define DJStatusTextViewCoverTag 999

@implementation DJStatusTextView


- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
        self.backgroundColor = [UIColor clearColor];
        self.editable = NO; // 禁止编辑
        self.textContainerInset = UIEdgeInsetsMake(0, -5, 0, -5);
        self.scrollEnabled = NO; // 禁止滚动
        
    }
    return self;
}


// 类似于android里的 MotionEvent.ACTION_DOWN
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    UITouch *touch =  [touches anyObject];
    // 获取触摸点的坐标
    CGPoint touchPoint = [touch locationInView:self];
    
    
    NSArray *specialTextArray = [self.attributedText attribute:@"special" atIndex:0 effectiveRange:NULL];
    BOOL contains = NO;
    
    for (DJSpecialText *specialText in specialTextArray) {
        
        self.selectedRange = specialText.range;
        // 获取选中范围的矩形框
        NSArray *rects = [self selectionRectsForRange:self.selectedTextRange];
        // 获取到矩形框后就将选中范围清空
        self.selectedRange = NSMakeRange(0, 0);
        
        for (UITextSelectionRect *selectionRect in rects) {
            CGRect rect = selectionRect.rect;
            if (rect.size.width == 0 || rect.size.height == 0) continue;
            
            if (CGRectContainsPoint(rect, touchPoint)) {
                contains = YES;
                break;
            }
        }
        
        if (contains) {
            
            for (UITextSelectionRect *selectionRect in rects) {
                CGRect rect = selectionRect.rect;
                if (rect.size.width == 0 || rect.size.height == 0) continue;
                
                UIView *cover = [[UIView alloc] init];
                cover.backgroundColor = DJColor(179,193, 211);
                cover.frame = rect;
                cover.tag = DJStatusTextViewCoverTag;
                cover.layer.cornerRadius = 3;
                [self insertSubview:cover atIndex:0]; // 将当前View插入到特殊文本的下面
                
            }
            break;
        }
        
    }

}


// 类似于android里的 MotionEvent.ACTION_UP
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self touchesCancelled:touches withEvent:event];
    });

}


// 当触摸事件被打断时调用此方法
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    // 去掉特殊字符后面的高亮背景
    for (UIView *child in self.subviews) {
        if (child.tag == DJStatusTextViewCoverTag) [child removeFromSuperview];
    }

}


- (BOOL)canBecomeFirstResponder {
    return NO;
}


@end

最终效果:

技术分享

新浪微博客户端(58)-处理点击微博内容中的关键字