版权声明:本文为博主原创文章,未经博主允许不得转载。
指示根视图:(准备几张图片,把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);
}
}
}
最终效果:
原文地址:http://blog.csdn.net/qq_31810357/article/details/50124869