天天看点

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