含有Emoji表情的文本計算高度

屏幕快照 2016-11-13 下午9.55.05.png

最進開發(fā)社區(qū)時遇到一個需求,產(chǎn)品那邊的需求是要做成和QQ空間一樣的評論功能,在評論內(nèi)容中要顯示昵稱,并且點擊昵稱要進入個人主頁。查了好多資料,看了YYText和TTTAttributedLabel的官方文章,也沒找到結(jié)果,最后自己抱著試一試的態(tài)度,結(jié)果還真的實現(xiàn)了需求,記錄下來,分享給大家,希望對你們會有所幫助
先來一張效果圖

7E8F2CA3-1F82-4993-9423-AE46D6FFF4EA.png

這個是最后的效果圖,點擊淺藍色文字會跳到個人主頁,不過還有點小問題,文字的間距還需要微調(diào)下。不過思路已經(jīng)有了。
先說下自己遇到的問題。點擊文字鏈接用的是YYText,實現(xiàn)起來很簡單,但是問題是,當(dāng)字符串中含有Emoji表情時,行間距就出現(xiàn)的了問題。本來我們需要的是這樣的。

屏幕快照 2016-11-13 下午9.22.58.png

但是使用YYText或者TTTAttributedLabel后變成了這樣

屏幕快照 2016-11-13 下午9.26.41.png

間距明顯不一樣

首先說明下,對于含有Emoji表情的字符串,使用UILabel來展示沒有任何問題,間距也都是一樣的,但是使用YYText或者TTTAttributedLabel來添加文字的點擊事件之后都會變成含有Emoji表情的行高比正常文字的行高要高。
本以為YYText或者TTTAttributedLabel本身有方法可以設(shè)置,很遺憾,我沒找到(如果你知道的話,請留言告訴我),無奈之下只能使用比較笨的方法。
先說下我的思路:目前的結(jié)果是含有Emoji表情的行高要比預(yù)期的高,于是就想到,能不能獲取每行的內(nèi)容,然后循環(huán)遍歷每行的文字,判斷是否含友Emoji表情,如果有則不做處理,如果沒有這設(shè)置行高和含有Emoji表情的行高一樣的高度,問題不就解決了嗎。
第一步:先要獲取,每行的文字

/**
 *  獲取每行的文字
 *
 *  @param text     文本內(nèi)容
 *  @param font     字體
 *  @param maxWidth 容器的最大寬度
 *
 *  @return 存儲每行文字的數(shù)組
 */

- (NSArray *)getSeparatedLinesFromtext:(NSString *)text font:(UIFont *)font maxWidth:(CGFloat)maxWidth
{
    CTFontRef myFont = CTFontCreateWithName((__bridge CFStringRef)([font fontName]), [font pointSize], NULL);
    NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] initWithString:text];
    [attStr addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)myFont range:NSMakeRange(0, attStr.length)];
    
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attStr);
    
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, CGRectMake(0,0,maxWidth,100000));
    
    CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, NULL);
    
    NSArray *lines = (__bridge NSArray *)CTFrameGetLines(frame);
    NSMutableArray *linesArray = [[NSMutableArray alloc]init];
    
    for (id line in lines)
    {
        CTLineRef lineRef = (__bridge CTLineRef )line;
        CFRange lineRange = CTLineGetStringRange(lineRef);
        NSRange range = NSMakeRange(lineRange.location, lineRange.length);
        
        NSString *lineString = [text substringWithRange:range];
        [linesArray addObject:lineString];
    }
    return (NSArray *)linesArray;
}

使用此方法,可以獲取每行的文字的內(nèi)容。
第二步:判斷是否含有Emoji表情

//判斷是否含有Emoji表情
+ (BOOL)stringContainsEmoji:(NSString *)string
{
    __block BOOL returnValue =NO;
    [string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        const unichar hs = [substring characterAtIndex:0];
        // surrogate pair
        if (0xd800) {
            if (0xd800 <= hs && hs <= 0xdbff) {
                if (substring.length > 1) {
                    const unichar ls = [substring characterAtIndex:1];
                    const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                    if (0x1d000 <= uc && uc <= 0x1f77f) {
                        returnValue =YES;
                    }
                }
            }else if (substring.length > 1) {
                const unichar ls = [substring characterAtIndex:1];
                if (ls == 0x20e3) {
                    returnValue =YES;
                }
            }else {
                // non surrogate
                if (0x2100 <= hs && hs <= 0x27ff) {
                    returnValue =YES;
                }else if (0x2B05 <= hs && hs <= 0x2b07) {
                    returnValue =YES;
                }else if (0x2934 <= hs && hs <= 0x2935) {
                    returnValue =YES;
                }else if (0x3297 <= hs && hs <= 0x3299) {
                    returnValue =YES;
                }else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
                    returnValue =YES;
                }
            }
        }
    }];
    return returnValue;
}

第三步:循環(huán)存儲每行文字內(nèi)容的數(shù)組,處理字符串

- (NSMutableAttributedString *)changeLineSpacing:(NSArray *)stringList {
    NSMutableAttributedString *mutableString = [[NSMutableAttributedString alloc] init];
    for (NSString *string in stringList) {
//如果含有Emoji表情,不做處理
        if ([NSString stringContainsEmoji:string]) {
            NSMutableAttributedString *contentEmojistring = [[NSMutableAttributedString alloc] initWithString:string];
            [mutableString appendAttributedString:contentEmojistring];
        }else { //否則設(shè)置段落樣式,行高為4(這個高度要根據(jù)自己的需求慢慢的試)
            NSMutableAttributedString *unContentEmojistring = [[NSMutableAttributedString alloc] initWithString:string];
            NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
            paragraphStyle.lineSpacing = 4;
            [unContentEmojistring addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [unContentEmojistring length])];
            [mutableString appendAttributedString:unContentEmojistring];
        }
    }
    return mutableString; //返回最后處理完成的字符串
}

此時你看到的效果是這樣的

屏幕快照 2016-11-13 下午9.41.33.png

這樣就實現(xiàn)了需求了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,359評論 4 61
  • 工具版李芳艷20170625 感恩遇見 工具的學(xué)習(xí)是耗時的,但為了讓自己掌控好自己的生活。我必須去嘗試找到適合自己...
    芬芳艷麗與你同享閱讀 483評論 1 2
  • 前些天回老家,跟著父母去看望鄉(xiāng)下的奶奶,下午在院子里陪奶奶聊天的時候,無意中提起了爺爺,看奶奶提起爺爺?shù)男δ?,好?..
    心有君玉閱讀 572評論 0 6
  • 拉上窗簾 閉上了眼 腦中全是你的模樣 你優(yōu)美的身姿 你美麗的臉龐 如春風(fēng)一樣滋養(yǎng)心田 記得那天 我拉著你的手 走在...
    喬邊故事閱讀 177評論 0 1
  • 【原文】(9.28) 子曰:“歲寒,然后知松柏之后彫后也。” 【通譯】 孔子說:“到了寒冷季節(jié)...
    錢江潮369閱讀 637評論 2 2

友情鏈接更多精彩內(nèi)容