zoukankan      html  css  js  c++  java
  • 新浪微博客户端(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)];

    DJSpecialText.h

    #import <Foundation/Foundation.h>
    
    @interface DJSpecialText : NSObject
    
    /** 特殊文本的内容 */
    @property (nonatomic,copy) NSString *text;
    /** 特殊文本的范围 */
    @property (nonatomic,assign) NSRange range;
    /** 特殊文本的矩形框 NSArray中存放的是CGRect对象 */
    @property (nonatomic,strong) NSArray *rects;
    
    @end

    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];
        
        // 计算特殊文本所在的矩形框
        [self setupAttributedTextRects];
        
        // 根据触摸点判断是否在点击的是特殊文本
        DJSpecialText *specialText = [self specialTextWithTouchPoint:touchPoint];
        
        // 如果是特殊文本,则为其添加一个浅色背景
        if (specialText) {
            
            NSArray *rectArray = specialText.rects;
            for (NSValue *rectValue in rectArray) {
                CGRect rect =  rectValue.CGRectValue; // 取出当前文本所在的CGRect
                // 添加浅色背景
                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];
                
            }
        }
        
        DJLog(@"点击了TextView.......");
        
    }
    
    
    
    /** 计算特殊文本所在的CGRect,并将其作为特殊文本的属性 */
    - (void)setupAttributedTextRects {
    
        NSArray *specialTextArray = [self.attributedText attribute:@"special" atIndex:0 effectiveRange:NULL];
        
        for (DJSpecialText *specialText in specialTextArray) {
            
            // 设置当前TextView选中范围
            self.selectedRange = specialText.range;
            // 获取选中文字的CGRect
            NSArray *selectionRects =  [self selectionRectsForRange:self.selectedTextRange];
            // 清空当前TextView选中范围
            self.selectedRange = NSMakeRange(0, 0);
            
            NSMutableArray *attributeTextRects = [NSMutableArray array]; // 属性文本所在的CGRect数组
            
            for (UITextSelectionRect *selectionRect in selectionRects) {
                // 取出当前特殊文本所在的CGRect
                CGRect rect =  selectionRect.rect;
                // 若存在垃圾矩形框,则跳过
                if (rect.size.width == 0 || rect.size.height == 0) continue;
                // 添加当前CGRect到其所在的CGRect数组(由于CGRect是结构体,无法直接添加到NSArray当中,故需要将其转换为NSValue对象,再添加到数组)
                [attributeTextRects addObject:[NSValue valueWithCGRect:rect]];
            }
            
            // 将特殊文本所在CGRect集合设置进去
            specialText.rects = attributeTextRects;
        }
        
    }
    
    
    
    /** 传入一个触摸点,返回当前触摸点所在的特殊文本,若没有,则返回空 */
    - (DJSpecialText *)specialTextWithTouchPoint:(CGPoint)touchPoint {
    
        NSArray *specialTextArray = [self.attributedText attribute:@"special" atIndex:0 effectiveRange:NULL];
        
        for (DJSpecialText *specialText in specialTextArray) {
           
           // 取出特殊文本所在的CGRect范围
           NSArray *rectArray = specialText.rects;
           
            // 遍历当前特殊文本所在的矩形框
            for (NSValue *rectValue in rectArray) {
                if (CGRectContainsPoint(rectValue.CGRectValue, touchPoint)) {
                    return specialText; // 若当前矩形框包含触摸点,则将该特殊文本返回
                }
            }
        }
        
        return nil;
    }
    
    
    
    // 类似于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];
        }
    
    }
    
    
    // iOS触摸事件传递
    // 1.判断点在谁身上,调用pointInside,返回YES的控件就是触摸点所在的控件
    // 2.由触摸点所在的UI控件选出处理事件的UI控件,调用hitTest:(CGPoint)point withEvent
    
    
    // 此方法是用来决定触摸事件是由该控件上的哪一个子控件来处理
    //- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    //
    //
    //}
    
    
    // 这个方法类似于android里面的onTouchEvent,需要返回一个布尔值,该布尔值代表是否由该控件消费掉此触摸事件
    - (BOOL)pointInside:(CGPoint)touchPoint withEvent:(UIEvent *)event {
    
        [self setupAttributedTextRects];
        DJSpecialText *specialText = [self specialTextWithTouchPoint:touchPoint];
        if (specialText) { // 判断当前触摸点是否在特殊文本之上,若在,则认为是点击了特殊文本;若不在,则认为是点击了tableView上的Cell.
            return YES;
        } else {
            return NO;
        }
    
    }
    
    
    @end

    最终效果:

  • 相关阅读:
    Mac root Operation not permitted
    case_for_if 各种嵌套相结合
    RANDOM 的用法
    hdu 6681 Rikka with Cake(扫描线)
    2019牛客暑期多校训练营(第十场)F.Popping Balloons(线段树)
    2019 Multi-University Training Contest 2 Harmonious Army(最小割)
    P1361 小M的作物 (最小割)
    2019 Multi-University Training Contest 1 String(序列自动机+贪心)
    2019牛客暑期多校训练营(第九场)E.All men are brothers(并查集+排列组合)
    2019 Multi-University Training Contest 1 Path(最短路+最小割)
  • 原文地址:https://www.cnblogs.com/yongdaimi/p/6172271.html
Copyright © 2011-2022 走看看