美文网首页iOS即时通讯程序猿的人文与技术
富文本编辑(点击文字跳转与图文混排)

富文本编辑(点击文字跳转与图文混排)

作者: 月咏蝴蝶 | 来源:发表于2016-01-11 14:18 被阅读1142次

    点击问题跳转

    在这里我使用了两种方式去实现,一种是使用CoreText,另外一种是使用UITextView(基于TextKit,iOS7之后才可以使用)

    CoreText

    声明一个局部变量
    @interface ReplyTextView()
    {
        CTFrameRef frame;
    }
    绘制字符串,@XXX部分使用蓝色字体(在本例子中是self.to_user_name部分)
    - (void)drawRect:(CGRect)rect {
        // Drawing code
        if (self.user_name && self.to_user_name && self.content) {
            NSString *combineText = [NSString stringWithFormat:@"%@@%@   %@",self.user_name,self.to_user_name,self.content];
            self.combineAttText = [[NSMutableAttributedString alloc] initWithString:combineText];
    
            [self.combineAttText beginEditing];
    
            CTFontRef font = CTFontCreateWithName(CFSTR("AlNilePUA"), 12, NULL);
            [self.combineAttText addAttribute:(__bridge id)kCTFontAttributeName value:(__bridge id)font range:NSMakeRange(0, self.combineAttText.length)];
    
            // set user_name Color
            [self.combineAttText addAttribute:(__bridge id)kCTForegroundColorAttributeName value:RGBCOLOR(37, 40, 57) range:NSMakeRange(0, self.user_name.length)];
    
            // set to_user_name Color
            [self.combineAttText addAttribute:(__bridge id)kCTForegroundColorAttributeName value:RGBCOLOR(8, 120, 198) range:NSMakeRange(self.user_name.length, self.to_user_name.length + 3)];
    
            // set content Color
            [self.combineAttText addAttribute:(__bridge id)kCTForegroundColorAttributeName value:RGBCOLOR(130, 130, 130) range:NSMakeRange(self.combineAttText.length - self.content.length, self.content.length)];
    
            [self.combineAttText endEditing];
    
            // CTFramesetter是CTFrame的创建工厂,NSAttributedString需要通过CTFrame绘制到界面上,得到CTFramesetter后,创建path(绘制路径),然后得到CTFrame,最后通过CTFrameDraw方法绘制到界面上  
            CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.combineAttText);
            CGMutablePathRef path = CGPathCreateMutable();
            CGPathAddRect(path, NULL ,CGRectMake(0, -2, self.bounds.size.width, self.bounds.size.height));
    
            if (frame != nil) {
                CFRelease(frame);
            }
            frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
    
            //获取当前(View)上下文以便于之后的绘画,这个是一个离屏。
            CGContextRef context = UIGraphicsGetCurrentContext();
    
            CGContextSetTextMatrix(context , CGAffineTransformIdentity);
    
            //压栈,压入图形状态栈中.每个图形上下文维护一个图形状态栈,并不是所有的当前绘画环境的图形状态的元素都被保存。图形状态中不考虑当前路径,所以不保存
            //保存现在得上下文图形状态。不管后续对context上绘制什么都不会影响真正得屏幕。
            CGContextSaveGState(context);
    
            //x,y轴方向移动
            CGContextTranslateCTM(context , 0 ,self.bounds.size.height);
    
            //缩放x,y轴方向缩放,-1.0为反向1.0倍,坐标系转换,沿x轴翻转180度
            CGContextScaleCTM(context, 1.0 ,-1.0);
    
            CTFrameDraw(frame,context);
    
            CGPathRelease(path);
            CFRelease(framesetter);
    
        }
    }
    判断点击文字的位置
    - (long)indexAtPoint:(CGPoint)point{
        point = CGPointMake(point.x, CGRectGetMaxY(self.bounds) - point.y); // 这里Y坐标系是反的,所以需要减
        NSArray *lines = (__bridge NSArray *)(CTFrameGetLines(frame));
    
        CGPoint origins[lines.count];
        CTFrameGetLineOrigins(frame, CFRangeMake(0, lines.count), origins);
    
        for(int i = 0; i < lines.count; i++) {
            if(point.y > origins[i].y) {
                CTLineRef line = (__bridge CTLineRef)([lines objectAtIndex:i]);
                return CTLineGetStringIndexForPosition(line, point);
            }
        }
        return 0;
    }
    这里是点击的时候判断点击位置,如果点击@XXX则做相应操作
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        UITouch *user_touch = [touches anyObject];
        CGPoint touch_point = [user_touch locationInView:self];
        long index = [self indexAtPoint:touch_point];
        if (index > self.user_name.length && index < self.user_name.length + self.to_user_name.length + 3) {
            // touch @user
            if ([self.delegate respondsToSelector:@selector(touchShowHomePageArea:)]) {
                [self.delegate touchShowHomePageArea:YES];
            }
        }
        else{
            // reply somebody
            if ([self.delegate respondsToSelector:@selector(touchShowHomePageArea:)]) {
                [self.delegate touchShowHomePageArea:NO];
            }
        }
    }

    使用UITextView(TextKit)

    这里使用UITextView则简单得多

    这里创建一个基于UITextView的类
    #pragma mark - DrawCode
    - (void)drawRect:(CGRect)rect {
        if (self.user_name && self.to_user_name && self.content) {
            NSString *combineText = [NSString stringWithFormat:@"%@@%@:%@",self.user_name,self.to_user_name,self.content];
            self.attributedText = [[NSMutableAttributedString alloc] initWithString:combineText];
            // 设置常规属性
            [self setUpNormalAttribute];
    
            // 设置表情链接
            [self setUpEmojiAndLink];
            // 注:点击链接反馈直接在UITextViewDelegate里面
        }
    }
    #pragma mark - 设置常规属性
    - (void)setUpNormalAttribute{
        // 注:不能直接使用attributedText,只能copy然后再赋值
        NSMutableAttributedString *mutStr = [self.attributedText mutableCopy];
        // 设置评论人名字属性
        [mutStr addAttributes:@{NSForegroundColorAttributeName :RGBCOLOR(37, 40, 57),
                                NSFontAttributeName :[UIFont systemFontOfSize:12.0]} range:NSMakeRange(0,[self.user_name length])];
        // 设置内容
        [mutStr addAttributes:@{NSForegroundColorAttributeName :RGBCOLOR(130, 130, 130),
                                NSFontAttributeName :[UIFont systemFontOfSize:12.0]} range:NSMakeRange(mutStr.length - [self.content length],[self.content length])];
        self.attributedText = [mutStr copy];
    }
    #pragma mark - 设置表情链接
    - (void)setUpEmojiAndLink{
        NSMutableAttributedString * mutStr = [self.attributedText mutableCopy];
        // 添加链接(点击链接反馈直接在UITextViewDelegate里面)
    
        NSURL *url = [NSURL URLWithString:self.to_user_id];
        [mutStr addAttribute:NSLinkAttributeName value:url range:NSMakeRange([self.user_name length],[self.to_user_name length] + 1)];
    
        self.attributedText = [mutStr copy];
    }

    图文混排

    这里图文混排给予UITextView

    设置图片以及插入位置
    - (void)setUpEmojiAndLink{
        NSMutableAttributedString *mutStr = [self.textView.attributedText mutableCopy];
        // Add Emoji
        UIImage *image1 = [UIImage imageNamed:@"emoji"];
        NSTextAttachment *attachment1 = [[NSTextAttachment alloc] init];
        attachment1.bounds = CGRectMake(0, 0, 30, 30);
        attachment1.image = image1;
        NSAttributedString *attStr1 = [NSAttributedString attributedStringWithAttachment:attachment1];
        [mutStr insertAttributedString:attStr1 atIndex:30];
        // Add Emoji2
        UIImage *image2 = [UIImage imageNamed:@"label1"];
        NSTextAttachment *attachment2 = [[NSTextAttachment alloc] init];
        attachment2.bounds = CGRectMake(0, 0, 50, 10);
        attachment2.image = image2;
        NSAttributedString *attStr2 = [NSAttributedString attributedStringWithAttachment:attachment2];
        [mutStr insertAttributedString:attStr2 atIndex:40];
        [self.textView setAttributedText:[mutStr mutableCopy]];
    }
    设置环绕路径
    - (void)setLoopPath{
        // Set Location Of ImageView
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(120, 20, 100, 50)];
        imageView.image = [UIImage imageNamed:@"label2"];
        [self.view addSubview:imageView];
        // Set Loop Path
        UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(100, 15, 100, 50)];
        self.textView.textContainer.exclusionPaths = @[path];
    }

    效果图


    DCC91AA8-5292-4BD1-AB03-A1843EC0D179.png


    参考博客:龙炎其实是王老师
    参考博客:欧阳剑心

    相关文章

      网友评论

      • ios肖:有没有,图片加文字,在变色+文字点击事件
      • f20369f93c07:有demo吗,借鉴下

      本文标题:富文本编辑(点击文字跳转与图文混排)

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