CoreText的简单实用demo
这里我封装了一个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相关推荐
- PHPExcel----保存/导出excel文档数据【简单实用demo】
首先要有PHPExcel类:传送门 只需要保存其中的Classes即可. 在项目中引用PHPExcel.php 我这里放在同目录下: include("./PHPExcel/PHPExcel ...
- 一个简单实用的,基于EF的三层架构
到底什么样的框架才是好框架呢?或许不同人有不同的看法.我个人觉一个好的框架,最重要的要是简单实用,能快速适开发,可维护性高(不会出现复制黏贴的代码),并能快速响应各种业务场景的变化的框架,同时性能不会 ...
- CSS3 linear-gradient线性渐变实现虚线等简单实用图形
一.作为图片存在的CSS3 gradient渐变 我觉得CSS3 Backgrounds比较厉害的一个地方就是支持多背景,也就是背景图片个数可以无限累加,正好CSS3的gradient渐变性质是 ba ...
- jcrop java_[Java教程]Jcrop简单实用
[Java教程]Jcrop简单实用 0 2014-05-06 12:00:10 今天有一个项目的功能需求 "在上传照片的时候能进行裁剪",网上找了下,发现有Jcrop这款插件,自己 ...
- html简单图片放大镜,jQuery轻量级简单实用的图片放大镜特效
zoomtoo是一款轻量级的简单实用的jQuery图片放大镜特效插件.这个图片放大镜特效在鼠标滑过骨牌的时候,在原来图片区域内部将图片放大.鼠标进入和离开图片区域时都带有淡入淡出的效果.该图片放大镜插 ...
- html 可调节进度条控件,jQuery简单实用的轻量级进度条插件
jQMeter是一款简单实用的轻量级进度条jQuery插件,它可以显示为水平或垂直进度条,进度条加载时带有动画特效,你只需要简单的传入一些参数到jQMeter对象的构造函数中就可以完成你想要的进度条效 ...
- 分享几个用 Python 给图片添加水印的方法,简单实用
作者 |俊欣 来源 |关于数据分析与可视化 今天来分享几种可以给图片添加水印的方法,都是十分的简单实用,大家在看了之后也可以私底下去自己试试,有些方法需要的代码量就比较少,有些方法需要的代码量就稍微多 ...
- matlab简单程序实例_visual basic VB.NET实例系列教程第一节(简单实用抽奖程序)...
近期疫情原因,工作比较不忙,所以打算出一套零基础,VB.NET实例系列入门教程,实用又好玩,带大家进入VB的编程世界里,希望这套图文教程能帮到有需要的人! 第一节(简单实用抽奖程序) 内容准备:编译环 ...
- 用aspnetpager实现datalist分页(绝对的简单实用)
微软的Datalist在做电子相册时候必不可少,但是不支持分页功能,都出到2008了还是没有分页功能,幸好网上有个专业的分页空间aspnetpager,帮我们解决了大问题,说实在话的,网上关于data ...
最新文章
- 别再用那些已经淘汰的技术了!2020年9大顶级Java框架出炉!!
- python中文意思k-Python中_,__,__xx__的区别
- Web前端开发css基础样式总结
- SATA硬盘如何使用GHOSTSATA硬盘如何使用GHOST
- Android官方开发文档Training系列课程中文版:性能优化建议
- 第八章 基本脚本编译
- leetcode 241 python
- python开发gui实战_python实战GUI界面+mysql
- html toggle自动隐藏,Javascript / HTML – 切换可见性(当另一个div元素呈现可见时自动导致一个div元素隐藏)...
- 网工考试——网络体系结构、物理层和数据通信
- mtk无线网卡 linux,Linux下安装MT7601U无线网卡驱动
- CV520国产替代Ci521 13.56MHz 非接触式读写器芯片
- ThingJS摄像机总结
- 共享单车原理大揭秘:小编亲自示范如何“撬锁”
- 卷不能在读/写模式下重新挂载。可能是因为先前没有完全卸载(安全删除)
- 5个物联网商业案例及其带给我们的启示
- badatatable转成json_数据表转换成json(DatatableToJson)
- 夜晚图像的目标检测-matlab
- php个人博客程序推荐,推荐五款不错的个人博客程序
- 特征选择过滤法-方差过滤、F检验、互信息法