这里我封装了一个View用于显示文字与图片的混排,首先我们需要先在你的项目中添加coreText框架,在使用时直接导入头文件即可


核心代码:

.h中

#import <UIKit/UIKit.h>

#import <CoreText/CoreText.h>

使用代理,进行传值,这里我将段落的高度作为传递的参数,传给View的上级页面

@protocol ZHPCoreTextDelegate <NSObject>

@optional

- (void)ViewHeight:(CGFloat)height;

@end

@interface ZHPCoreTextView : UIView

- (id)initWithFrame:(CGRect)frame text:(NSString *)text imageNameArray:(NSArray *)imageNameArray delegate:(id<ZHPCoreTextDelegate>)delegate;

@property (nonatomic,copy)NSArray *imageArray;

@property (nonatomic,copy)NSString *text;

@property (nonatomic,assign)CGRect frame;

@property (nonatomic,strong)id<ZHPCoreTextDelegate> delegate;

@end

.m中

这里设置图片的高度与宽度

void RunDelegateDeallocCallback( void* refCon ){

}

CGFloat RunDelegateGetAscentCallback( void *refCon ){

NSString *imageName = (__bridge NSString *)refCon;

//    return [UIImage imageNamed:imageName].size.height;

return 15;

}

CGFloat RunDelegateGetDescentCallback(void *refCon){

return 0;

}

CGFloat RunDelegateGetWidthCallback(void *refCon){

NSString *imageName = (__bridge NSString *)refCon;

//    return [UIImage imageNamed:imageName].size.width;

return 25;

}

- (id)initWithFrame:(CGRect)frame text:(NSString *)text imageNameArray:(NSArray *)imageNameArray delegate:(id<ZHPCoreTextDelegate>)delegate

{

self = [super initWithFrame:frame];

if (self) {

self.backgroundColor = [UIColor whiteColor];

_delegate = delegate;

_text = text;

_imageArray = imageNameArray;

}

return self;

}

drawRect,将图片与文字绘制在画布上

- (void)drawRect:(CGRect)rect

{

[super drawRect:rect];

CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSetTextMatrix(context, CGAffineTransformIdentity);

CGContextTranslateCTM(context, 0, self.bounds.size.height);

CGContextScaleCTM(context, 1.0, -1.0);

NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@",_text] ];

//为所有文本设置字体

//[attributedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:24] range:NSMakeRange(0, [attributedString length])]; // 6.0+

[attString addAttribute:(NSString *)kCTForegroundColorAttributeName value:(id)[UIColor orangeColor].CGColor range:NSMakeRange(0, _text.length)];

for (int i = _imageArray.count-1; i>= 0; i--) {

NSString *imageName = [_imageArray objectAtIndex:i];

CTRunDelegateCallbacks imageCallbacks;

imageCallbacks.version = kCTRunDelegateVersion1;

imageCallbacks.dealloc = RunDelegateDeallocCallback;

imageCallbacks.getAscent = RunDelegateGetAscentCallback;

imageCallbacks.getDescent = RunDelegateGetDescentCallback;

imageCallbacks.getWidth = RunDelegateGetWidthCallback;

CTRunDelegateRef runDelegate = CTRunDelegateCreate(&imageCallbacks, (__bridge void * _Nullable)(imageName));

NSMutableAttributedString *imageAttributedString = [[NSMutableAttributedString alloc] initWithString:@" "];//空格用于给图片留位置

[imageAttributedString addAttribute:(NSString *)kCTRunDelegateAttributeName value:(__bridge id)runDelegate range:NSMakeRange(0, 1)];

CFRelease(runDelegate);

//    图片所占字节大小

[imageAttributedString addAttribute:@"imageName" value:imageName range:NSMakeRange(0, 1)];

//    图片插入的位置

[attString insertAttributedString:imageAttributedString atIndex:_text.length];

}

UIFont *font = [UIFont systemFontOfSize:13];

CTFontRef fontRef = CTFontCreateWithName((__bridge CFStringRef)font.fontName,

font.pointSize,

NULL);

[attString addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)fontRef range:NSMakeRange(0, [attString length])];

CFRelease(fontRef);

//换行模式

CTParagraphStyleSetting lineBreakMode;

CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping;

lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;

lineBreakMode.value = &lineBreak;

lineBreakMode.valueSize = sizeof(CTLineBreakMode);

//行距

CGFloat _linespace = 2.0f;

CTParagraphStyleSetting lineSpaceSetting;

lineSpaceSetting.spec = kCTParagraphStyleSpecifierLineSpacing;

lineSpaceSetting.value = &_linespace;

lineSpaceSetting.valueSize = sizeof(float);

//首行缩进

CGFloat fristlineindent = 24.0f;

CTParagraphStyleSetting fristline;

fristline.spec = kCTParagraphStyleSpecifierFirstLineHeadIndent;

fristline.value = &fristlineindent;

fristline.valueSize = sizeof(float);

CTParagraphStyleSetting settings[] = {

lineBreakMode,

lineSpaceSetting,

fristline

};

CTParagraphStyleRef style = CTParagraphStyleCreate(settings, 3);

// build attributes

NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(id)style forKey:(id)kCTParagraphStyleAttributeName ];

// set attributes to attributed string

[attString addAttributes:attributes range:NSMakeRange(0, [attString length])];

CGMutablePathRef path = CGPathCreateMutable();

CGRect bounds = CGRectMake(0.0, 0.0, self.bounds.size.width, self.bounds.size.height);

CGPathAddRect(path, NULL, bounds);

CTFramesetterRef framesetter =

CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString); //3

CTFrameRef frame =

CTFramesetterCreateFrame(framesetter,

CFRangeMake(0, 0), path, NULL);

CTFrameDraw(frame, context); //4

//    计算段落高度

NSArray *linesArray = (NSArray *) CTFrameGetLines(frame);

CGPoint origins[[linesArray count]];

CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins);

int line_y = (int) origins[[linesArray count] -1].y;  //最后一行line的原点y坐标

CGFloat ascent;

CGFloat descent;

CGFloat leading;

CTLineRef line = (__bridge CTLineRef) [linesArray objectAtIndex:[linesArray count]-1];

CTLineGetTypographicBounds(line, &ascent, &descent, &leading);

[_delegate ViewHeight:self.bounds.size.height - line_y + (int) descent +1];

//+1为了纠正descent转换成int小数点后舍去的值

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);

CGFloat lineAscent;

CGFloat lineDescent;

CGFloat lineLeading;

CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);

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* attributes = (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 = [attributes objectForKey:@"imageName"];

//图片渲染逻辑

if (imageName) {

UIImage *image = [UIImage imageNamed:imageName];

if (image) {

CGRect imageDrawRect;

imageDrawRect.size = CGSizeMake(20, 20);

imageDrawRect.origin.x = runRect.origin.x + lineOrigin.x ;

imageDrawRect.origin.y = lineOrigin.y-5;

CGContextDrawImage(context, imageDrawRect, image.CGImage);

}

}

}

}

CFRelease(frame); //5

CFRelease(path);

CFRelease(framesetter);

}

其他文件使用时:

- (void)viewDidLoad {

[super viewDidLoad];

_view = [[ZHPCoreTextView alloc] initWithFrame:CGRectMake(100, 100, self.view.frame.size.width/2, self.view.frame.size.height/2) text:@"什么时候变得不安,和没有归属感。然后还一味任性地埋怨,这不是我的错,如此焦躁,和孩子气的自己。忍不住的想放逐和流浪。看着依旧苍白的自己,像蒲草一样飘来飘去" imageNameArray:@[@"保.png",@"搬.png",@"票.png"] delegate:self];

_view.backgroundColor = [UIColor whiteColor];

_view.center = self.view.center;

[self.view addSubview:_view];

}

//通过代理方法获得段落的高度

- (void)ViewHeight:(CGFloat)height{

NSLog(@"段落高度为:%f",height);

}

CoreText的简单实用demo相关推荐

  1. PHPExcel----保存/导出excel文档数据【简单实用demo】

    首先要有PHPExcel类:传送门 只需要保存其中的Classes即可. 在项目中引用PHPExcel.php 我这里放在同目录下: include("./PHPExcel/PHPExcel ...

  2. 一个简单实用的,基于EF的三层架构

    到底什么样的框架才是好框架呢?或许不同人有不同的看法.我个人觉一个好的框架,最重要的要是简单实用,能快速适开发,可维护性高(不会出现复制黏贴的代码),并能快速响应各种业务场景的变化的框架,同时性能不会 ...

  3. CSS3 linear-gradient线性渐变实现虚线等简单实用图形

    一.作为图片存在的CSS3 gradient渐变 我觉得CSS3 Backgrounds比较厉害的一个地方就是支持多背景,也就是背景图片个数可以无限累加,正好CSS3的gradient渐变性质是 ba ...

  4. jcrop java_[Java教程]Jcrop简单实用

    [Java教程]Jcrop简单实用 0 2014-05-06 12:00:10 今天有一个项目的功能需求 "在上传照片的时候能进行裁剪",网上找了下,发现有Jcrop这款插件,自己 ...

  5. html简单图片放大镜,jQuery轻量级简单实用的图片放大镜特效

    zoomtoo是一款轻量级的简单实用的jQuery图片放大镜特效插件.这个图片放大镜特效在鼠标滑过骨牌的时候,在原来图片区域内部将图片放大.鼠标进入和离开图片区域时都带有淡入淡出的效果.该图片放大镜插 ...

  6. html 可调节进度条控件,jQuery简单实用的轻量级进度条插件

    jQMeter是一款简单实用的轻量级进度条jQuery插件,它可以显示为水平或垂直进度条,进度条加载时带有动画特效,你只需要简单的传入一些参数到jQMeter对象的构造函数中就可以完成你想要的进度条效 ...

  7. 分享几个用 Python 给图片添加水印的方法,简单实用

    作者 |俊欣 来源 |关于数据分析与可视化 今天来分享几种可以给图片添加水印的方法,都是十分的简单实用,大家在看了之后也可以私底下去自己试试,有些方法需要的代码量就比较少,有些方法需要的代码量就稍微多 ...

  8. matlab简单程序实例_visual basic VB.NET实例系列教程第一节(简单实用抽奖程序)...

    近期疫情原因,工作比较不忙,所以打算出一套零基础,VB.NET实例系列入门教程,实用又好玩,带大家进入VB的编程世界里,希望这套图文教程能帮到有需要的人! 第一节(简单实用抽奖程序) 内容准备:编译环 ...

  9. 用aspnetpager实现datalist分页(绝对的简单实用)

    微软的Datalist在做电子相册时候必不可少,但是不支持分页功能,都出到2008了还是没有分页功能,幸好网上有个专业的分页空间aspnetpager,帮我们解决了大问题,说实在话的,网上关于data ...

最新文章

  1. 别再用那些已经淘汰的技术了!2020年9大顶级Java框架出炉!!
  2. python中文意思k-Python中_,__,__xx__的区别
  3. Web前端开发css基础样式总结
  4. SATA硬盘如何使用GHOSTSATA硬盘如何使用GHOST
  5. Android官方开发文档Training系列课程中文版:性能优化建议
  6. 第八章 基本脚本编译
  7. leetcode 241 python
  8. python开发gui实战_python实战GUI界面+mysql
  9. html toggle自动隐藏,Javascript / HTML – 切换可见性(当另一个div元素呈现可见时自动导致一个div元素隐藏)...
  10. 网工考试——网络体系结构、物理层和数据通信
  11. mtk无线网卡 linux,Linux下安装MT7601U无线网卡驱动
  12. CV520国产替代Ci521 13.56MHz 非接触式读写器芯片
  13. ThingJS摄像机总结
  14. 共享单车原理大揭秘:小编亲自示范如何“撬锁”
  15. 卷不能在读/写模式下重新挂载。可能是因为先前没有完全卸载(安全删除)
  16. 5个物联网商业案例及其带给我们的启示
  17. badatatable转成json_数据表转换成json(DatatableToJson)
  18. 夜晚图像的目标检测-matlab
  19. php个人博客程序推荐,推荐五款不错的个人博客程序
  20. 特征选择过滤法-方差过滤、F检验、互信息法

热门文章

  1. docker 设计原理
  2. vue生命周期以及顺序
  3. java tess4j mave_Java 验证码识别库 Tess4j 学习
  4. Echart 柱状图,X轴斜着展示
  5. 【立创开源】两节锂电池8.4V充电电路(USB-5V充电)
  6. 2021年UI设计趋势
  7. SQL 向:在 mysql 中创建《SQL 经典实例》中的两个主要在用的表 emp 和 dept 供大家使用
  8. 神秘九芒星——助人者
  9. 3G手机视频开发平台
  10. drozer 找不到java_【安全测试】Drozer安装及使用