天天看點

iOS中 圖文混排/自定義圖文混排

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。

訓示根視圖:(準備幾張圖檔,把label加載在window上)

customlable *label =  [[customlable alloc]initwithframe:cgrectmake(0, 60, self.window.bounds.size.width, self.window.bounds.size.height)];  

  label.backgroundcolor = [uicolor greencolor];  

  [self.window addsubview:label];  

引進架構:

#import <coretext/coretext.h>

建一個類,繼承自uilabel

傳回圖檔的高:

// 傳回圖檔的高  

cgfloat rundelegategetascentcallback(voidvoid *refcon) {  

    nsstring *imagename = (__bridge nsstring *)refcon;  

    return [uiimage imagenamed:imagename].size.height;  

}  

傳回圖檔的寬:

// 傳回圖檔的寬  

cgfloat rundelegategetwidthcallback(voidvoid *refcon) {  

//    nsstring *imagename = (__bridge nsstring *)refcon;  

    // 讓繪制圖檔的寬度為螢幕的寬, 使文本中隻要遇到圖檔就換行(配合上面的換行模式)  

    // 如果不想換行可以直接傳回圖檔的寬  

    return [uiscreen mainscreen].bounds.size.width;  

cgfloat rundelegategetdescentcallback(voidvoid *refcon){  

    return 0;  

開始繪制及相關計算:

#import "customlable.h"  

#import <coretext/coretext.h>  

@implementation customlable  

- (void)drawrect:(cgrect)rect  

{  

    [super drawrect:rect];  

    // 建立繪制區域  

    cgmutablepathref path = cgpathcreatemutable();  

    cgpathaddrect(path, nil, cgrectmake(0, 0, self.bounds.size.width, self.bounds.size.height));  

    // 擷取目前用于繪制畫布的上下文, 用于後續将内容繪制到畫布上  

    cgcontextref context = uigraphicsgetcurrentcontext();  

    // 翻轉坐标系  

    // 參數1:文本寬度占label的比例(0 ~ 1)  

    // 參數2:水準方向文字逐漸往下(參數 > 0, 往上: 參數 < 0)偏移,如果是正數,逐漸向上偏移  

    // 參數3:在豎直方向上,從下往上每行文字逐漸往右(參數 > 0, 往左: 參數 < 0)偏移  

    // 參數4:文本首行的縱坐标占label的比例(-1 ~ 0)  

    // 參數5:文本整體往右(參數 > 0, 往左: 參數 < 0)偏移量  

    // 參數6:文本整體在縱坐标方向的偏移量,參數 > label的高度, 往下偏移, 參數 < label的高度, 往上偏移  

    cgcontextconcatctm(context, cgaffinetransformmake(1, 0, 0, -1, 0, self.bounds.size.height));  

    // 準備文本  

    nsmutableattributedstring *attrstring = [[nsmutableattributedstring alloc]initwithstring:@"ios程式在啟動時會建立一個主線程,而在一個線程隻能執行一件事情,如果在主線程執行某些耗時操作,例如加載網絡圖檔,下載下傳資源檔案等會阻塞主線程(導緻界面卡死,無法互動),是以就需要使用多線程技術來避免這類情況。ios中有三種多線程技術 nsthread,nsoperation,gcd,這三種技術是随着ios發展引入的,抽象層次由低到高,使用也越來越簡單。"];  

    // 改變字型大小  

    [attrstring addattribute:nsfontattributename value:[uifont systemfontofsize:24] range:nsmakerange(0, 5)];  

    // 改變字型顔色  

    [attrstring addattribute:nsforegroundcolorattributename value:[uicolor redcolor] range:nsmakerange(0, 5)];  

    // 換行模式 (當label的寬度不夠顯示内容或圖檔的時候就自動換行) (預設狀态下如果不夠顯示圖檔, 不會自動換行, 部分圖檔就會看不見)  

    ctparagraphstylesetting linebreakmode;  

    ctlinebreakmode linebreak = kctlinebreakbycharwrapping;  

    linebreakmode.spec = kctparagraphstylespecifierlinebreakmode;  

    linebreakmode.value = &linebreak;  

    linebreakmode.valuesize = sizeof(ctlinebreakmode);  

    ctparagraphstylesetting setting[] = {linebreakmode};  

    ctparagraphstyleref style = ctparagraphstylecreate(setting, 1);  

    nsmutabledictionary *attributes = [nsmutabledictionary dictionarywithobject:(__bridge id)style forkey:(id)kctparagraphstyleattributename];  

    [attrstring addattributes:attributes range:nsmakerange(0, attrstring.length)];  

    // 設定ctrundelegatecallbacks 擷取圖檔大小  

    ctrundelegatecallbacks imagecallbacks;  

    imagecallbacks.version = kctrundelegateversion1;  

    // 擷取圖檔的高 (可自由設定傳回的高)  

    imagecallbacks.getascent = rundelegategetascentcallback;  

    // 設定圖檔下一行文字距離圖檔的距離  

    imagecallbacks.getdescent = rundelegategetdescentcallback;  

    // 擷取圖檔的寬 (可自由設定傳回寬度)  

    imagecallbacks.getwidth = rundelegategetwidthcallback;  

    // 空格用于給圖檔留個位置  

    nsmutableattributedstring *imageattributedstring = [[nsmutableattributedstring alloc]initwithstring:@" "];  

    // 根據圖檔占用尺寸的大小給圖檔留位置顯示  

    ctrundelegateref rundelegate = ctrundelegatecreate(&imagecallbacks, (__bridge voidvoid *)(@"untitled.png"));  

    [imageattributedstring addattribute:(nsstring *)kctrundelegateattributename value:(__bridge id)rundelegate range:nsmakerange(0, 1)];  

    // 将圖檔顯示在指定位置  

    nsstring *imagekey = @"imagename";  

    [imageattributedstring addattribute:imagekey value:@"untitled.png" range:nsmakerange(0, 1)];  

    // 設定插入圖檔的位置  

    [attrstring insertattributedstring:imageattributedstring atindex:38];  

    //根據nsmutableattributedstring生成frame  

    ctframeref frame = ctframesettercreateframe(ctframesettercreatewithattributedstring((cfattributedstringref)attrstring), cfrangemake(0, attrstring.length), path, nil);  

    // 開始繪制  

    ctframedraw(frame, context);  

    cfarrayref lines = ctframegetlines(frame);  

    cgpoint lineorigins[cfarraygetcount(lines)];  

    ctframegetlineorigins(frame, cfrangemake(0, 0), lineorigins);  

    for (int i = 0; i < cfarraygetcount(lines); i++) {  

        ctlineref line = cfarraygetvalueatindex(lines, i);  

        cfarrayref runs = ctlinegetglyphruns(line);  

        for (int j = 0; j < cfarraygetcount(runs); j++) {  

            cgfloat runascent;  

            cgfloat rundescent;  

            cgpoint lineorigin = lineorigins[i];  

            ctrunref run = cfarraygetvalueatindex(runs, j);  

            nsdictionary *mattrinbutes = (nsdictionary *)ctrungetattributes(run);  

            cgrect runrect;  

            runrect.size.width = ctrungettypographicbounds(run, cfrangemake(0, 0), &runascent, &rundescent, null);  

            runrect = cgrectmake(lineorigin.x + ctlinegetoffsetforstringindex(line, ctrungetstringrange(run).location, null), lineorigin.y - rundescent, runrect.size.width, runascent + rundescent);  

            nsstring *imagename = [mattrinbutes objectforkey:imagekey];  

            // 圖檔的渲染邏輯  

            if (imagename) {  

                uiimage *image = [uiimage imagenamed:imagename];  

                cgrect imagedrawrect;  

                imagedrawrect.size = image.size;  

                /* 

                 * 這才是放置圖檔的真正坐标 

                 */  

                // 設定圖檔的在x坐标的位置  

                // imagedrawrect.origin.x = runrect.origin.x + lineorigin.x;  

                // 将圖檔放在label的中間  

                imagedrawrect.origin.x = (self.bounds.size.width - image.size.width) / 2;  

                // 設定圖檔在y坐标的位置  

                imagedrawrect.origin.y = lineorigin.y;  

                // 繪制圖檔  

                cgcontextdrawimage(context, imagedrawrect, image.cgimage);  

            }  

        }  

    }  

最終效果:

iOS中 圖文混排/自定義圖文混排

原文位址:http://blog.csdn.net/qq_31810357/article/details/50124869

繼續閱讀