TQRichTextView icon indicating copy to clipboard operation
TQRichTextView copied to clipboard

连续表情无法正常显示

Open Jerry-Wang-Developer opened this issue 11 years ago • 3 comments

[smile][smile][smile][smile][smile][smile][smile][smile][smile][smile]

无法显示正常

Jerry-Wang-Developer avatar Mar 20 '14 04:03 Jerry-Wang-Developer

确实发现这个bug了

dadpp avatar Mar 30 '15 12:03 dadpp

这个bug的问题,是因为下标计算错了 提供一下我修复好的算法

/**

  • 解析字符串中url内容生成Run对象
  • @param attributedString 内容
  • @return TQRichTextRunURL对象数组 */
  • (NSArray *)runsForAttributedString:(NSMutableAttributedString *)attributedString { NSString *markL = @"["; NSString *markR = @"]";

NSString *string = [NSString stringWithString:attributedString.string];

NSMutableArray *array = [NSMutableArray array]; NSMutableArray *stack = [[NSMutableArray alloc] init];

for (int i = 0, index = 0; i < string.length; i++, index++) { NSString *s = [string substringWithRange:NSMakeRange(i, 1)];

if (([s isEqualToString:markL]) || ((stack.count > 0) && [stack[0] isEqualToString:markL]))
{
    if (([s isEqualToString:markL]) && ((stack.count > 0) && [stack[0] isEqualToString:markL]))
    {
        [stack removeAllObjects];
    }

    [stack addObject:s];

    //  检测到表情结束符后,进行提取表情
    if ([s isEqualToString:markR] || (i == string.length - 1))
    {
        NSMutableString *emojiStr = [[NSMutableString alloc] init];
        for (NSString *c in stack)
        {
            [emojiStr appendString:c];
        }

        if ([[TQRichTextRunEmoji emojiStringArray] containsObject:emojiStr])
        {
            NSRange range = NSMakeRange(index + 1 - emojiStr.length, emojiStr.length);

            [attributedString replaceCharactersInRange:range withString:@" "];

            TQRichTextRunEmoji *run = [[TQRichTextRunEmoji alloc] init];
            run.range    = NSMakeRange(index + 1 - emojiStr.length, 1);
            run.text     = emojiStr;
            run.drawSelf = YES;
            [run decorateToAttributedString:attributedString range:run.range];

            [array addObject:run];
        }

        index -= (stack.count - 1); // 此下标是计算表情被替换后的下标
        [stack removeAllObjects];
    }
}

}

return array; }

huhood avatar May 22 '15 09:05 huhood

刚Checkout下来的代码,发现几个问题:

  1. 表情无法连续显示,解决方法: 在+ (NSArray *)runsForAttributedString:(NSMutableAttributedString *)attributedString方法中修改

            if ([emojiTags containsObject:emojiStr])
            {
                NSRange range = NSMakeRange(i + 1 - emojiStr.length, emojiStr.length);
    
                [attributedString replaceCharactersInRange:range withString:@" "];
    
    
    
                TQRichTextRunEmoji *run = [[TQRichTextRunEmoji alloc] init];
                run.range    = NSMakeRange(i + 1 - emojiStr.length, 1);
                run.text     = emojiImageNames[[emojiTags indexOfObject:emojiStr]];
                run.drawSelf = YES;
                [run decorateToAttributedString:attributedString range:run.range];
    
                [array addObject:run];
    
                // 解决连续表情无法显示的问题
                i = i - emojiStr.length + 1;
            }
    
  2. 文字颜色设置无效的问题:在TQRichTextView的- (void)drawRect:(CGRect)rect方法中,添加

            [attString addAttribute:(NSString *)kCTForegroundColorAttributeName value:(id)self.textColor.CGColor range:NSMakeRange(0,attString.length)];
    
  3. 如果一行中,只有表情或者只有英文+表情,会导致表情高度不对被压缩的问题(中文文字占用高度比小写英文多,所以表情会正常):

            if (richTextRun.drawSelf)
            {
                CGFloat runAscent,runDescent;
                CGFloat runWidth  = CTRunGetTypographicBounds(runRef, CFRangeMake(0,0), &runAscent, &runDescent, NULL);
                CGFloat runHeight = (lineAscent + lineDescent );
                CGFloat runPointX = runRect.origin.x + lineOrigin.x;
                CGFloat runPointY = lineOrigin.y ;
    
                // 解决如果只有表情没有文字,表情高度被压缩的问题
                CGRect runRectDraw = CGRectMake(runPointX, runPointY - 5, runWidth, runHeight);
                if (runRectDraw.size.height < runRectDraw.size.width) {
                    runRectDraw.size.height = runRectDraw.size.width;
                }
                [richTextRun drawRunWithRect:runRectDraw];
    
                [self.runRectDictionary setObject:richTextRun forKey:[NSValue valueWithCGRect:runRectDraw]];
        }
        else
        {
            if (richTextRun)
            {
                [self.runRectDictionary setObject:richTextRun forKey:[NSValue valueWithCGRect:runRect]];
            }
        }
    

chyo avatar Jun 11 '15 06:06 chyo