IOS 图文混排(CoreText.framework)详解及实例

所属分类: 软件编程 / IOS 阅读数: 1065
收藏 0 赞 0 分享

IOS 图文混排(CoreText.framework)

       本文主要介绍了IOS图文混排的资料,这里整理了在网上查找的内容,帮助理解,掌握这部分知识,以下就是整理的内容:   

利用CORETEXT进行图文混排。

实现代码:

void RunDelegateDeallocCallback( void* refCon ){ 
   
} 
 
CGFloat RunDelegateGetAscentCallback( void *refCon ){ 
  NSString *imageName = (NSString *)refCon; 
  return 80;//[UIImage imageNamed:imageName].size.height; 
} 
 
CGFloat RunDelegateGetDescentCallback(void *refCon){ 
  return 0; 
} 
 
CGFloat RunDelegateGetWidthCallback(void *refCon){ 
  NSString *imageName = (NSString *)refCon; 
  return 100;//[UIImage imageNamed:imageName].size.width; 
} 

先设置一个CTRun的委托,主要是用于指定对象的上行高,宽,或上下文释放时使用。

-(void)drawCharAndPicture 
{ 
  CGContextRef context = UIGraphicsGetCurrentContext(); 
   
  CGContextSetTextMatrix(context, CGAffineTransformIdentity);//设置字形变换矩阵为CGAffineTransformIdentity,也就是说每一个字形都不做图形变换 
   
  CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height); 
  CGContextConcatCTM(context, flipVertical);//将当前context的坐标系进行flip 
  NSLog(@"bh=%f",self.bounds.size.height); 
   
  NSMutableAttributedString *attributedString = [[[NSMutableAttributedString alloc] initWithString:@"请在这里插入一张图片位置"] autorelease]; 
   
   
  //为图片设置CTRunDelegate,delegate决定留给图片的空间大小 
  NSString *imgName = @"img.png"; 
  CTRunDelegateCallbacks imageCallbacks; 
  imageCallbacks.version = kCTRunDelegateVersion1; 
  imageCallbacks.dealloc = RunDelegateDeallocCallback; 
  imageCallbacks.getAscent = RunDelegateGetAscentCallback; 
  imageCallbacks.getDescent = RunDelegateGetDescentCallback; 
  imageCallbacks.getWidth = RunDelegateGetWidthCallback; 
  CTRunDelegateRef runDelegate = CTRunDelegateCreate(&imageCallbacks, imgName); 
  NSMutableAttributedString *imageAttributedString = [[NSMutableAttributedString alloc] initWithString:@" "];//空格用于给图片留位置 
  [imageAttributedString addAttribute:(NSString *)kCTRunDelegateAttributeName value:(id)runDelegate range:NSMakeRange(0, 1)]; 
  CFRelease(runDelegate); 
   
  [imageAttributedString addAttribute:@"imageName" value:imgName range:NSMakeRange(0, 1)]; 
   
  [attributedString insertAttributedString:imageAttributedString atIndex:4]; 
 //换行模式 
  CTParagraphStyleSetting lineBreakMode; 
  CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping; 
  lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode; 
  lineBreakMode.value = &lineBreak; 
  lineBreakMode.valueSize = sizeof(CTLineBreakMode); 
   
  CTParagraphStyleSetting settings[] = { 
    lineBreakMode 
  }; 
   
  CTParagraphStyleRef style = CTParagraphStyleCreate(settings, 1); 
   
     
  // build attributes 
  NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(id)style forKey:(id)kCTParagraphStyleAttributeName ]; 
   
  // set attributes to attributed string 
  [attributedString addAttributes:attributes range:NSMakeRange(0, [attributedString length])]; 
   
 
   
  CTFramesetterRef ctFramesetter = CTFramesetterCreateWithAttributedString((CFMutableAttributedStringRef)attributedString); 
   
  CGMutablePathRef path = CGPathCreateMutable(); 
  CGRect bounds = CGRectMake(0.0, 0.0, self.bounds.size.width, self.bounds.size.height); 
  CGPathAddRect(path, NULL, bounds); 
   
  CTFrameRef ctFrame = CTFramesetterCreateFrame(ctFramesetter,CFRangeMake(0, 0), path, NULL); 
  CTFrameDraw(ctFrame, context); 
   
  CFArrayRef lines = CTFrameGetLines(ctFrame); 
  CGPoint lineOrigins[CFArrayGetCount(lines)]; 
  CTFrameGetLineOrigins(ctFrame, CFRangeMake(0, 0), lineOrigins); 
  NSLog(@"line count = %ld",CFArrayGetCount(lines)); 
  for (int i = 0; i < CFArrayGetCount(lines); i++) { 
    CTLineRef line = CFArrayGetValueAtIndex(lines, i); 
    CGFloat lineAscent; 
    CGFloat lineDescent; 
    CGFloat lineLeading; 
    CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading); 
    NSLog(@"ascent = %f,descent = %f,leading = %f",lineAscent,lineDescent,lineLeading); 
     
    CFArrayRef runs = CTLineGetGlyphRuns(line); 
    NSLog(@"run count = %ld",CFArrayGetCount(runs)); 
    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); 
      NSLog(@"width = %f",runRect.size.width); 
       
      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 = image.size; 
          imageDrawRect.origin.x = runRect.origin.x + lineOrigin.x; 
          imageDrawRect.origin.y = lineOrigin.y; 
          CGContextDrawImage(context, imageDrawRect, image.CGImage); 
        } 
      } 
    } 
  } 
   
  CFRelease(ctFrame); 
  CFRelease(path); 
  CFRelease(ctFramesetter); 
} 

效果:


从上面看大家可能没有发现什么问题,当把图片放在字的最左边会是什么样子的?


因此为了避免这种情况发生,我在代码中添加了换行模式。添加换行后的效果:


感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

更多精彩内容其他人还在看

IOS开发相册图片多选和删除的功能

之前小编有和大家分享过一篇关于从相册选取单张照片的文章,那么下面这篇文章跟大家分享下如何相册多图选择和删除,以及包括拍照功能,有需要的可以参考学习,下面来一起看看吧。
收藏 0 赞 0 分享

iOS使用runtime修改文本框(TextField)的占位文字颜色

相信大家都知道TextField默认的占位颜色也是深灰色,这个颜色比较难看清,这篇文章给大家介绍如何使用runtime修改TextField文本框的占位文字颜色,有需要的可以参考借鉴.
收藏 0 赞 0 分享

iOS实现点击状态栏自动回到顶部效果详解

在IOS开发过程中,经常会有这种需求,需要通过点击状态栏返回到顶部,给用户更好的体验效果,下面这篇文章给大家详细介绍了实现过程,有需要的可以参考借鉴。
收藏 0 赞 0 分享

IOS上iframe的滚动条失效的解决办法

这篇文章主要为大家详细介绍了IOS上iframe的滚动条失效的解决办法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

IOS面试大全之常见算法

之前看了很多面试题,感觉要不是不够就是过于冗余,于是我将网上的一些面试题进行了删减和分类,这篇文章先给大家分享一下IOS中的常见算法,有需要的可以参考借鉴。
收藏 0 赞 0 分享

IOS判断字符串是否有空格实例

在我们大家日常开发的时候,经常会需要对注册,登录,忘记密码等功能的密码进行判断是否包含空格,下面这篇文章给大家分享了自己封装的一个方法,有需要的可以参考借鉴。
收藏 0 赞 0 分享

IOS设置按钮为圆角的示例代码

这篇文章给大家分享了IOS按钮设置为圆角的方法,按钮的四个角都可随意设置为圆角,对大家开发IOS具有一定的参考借鉴价值。有需要的朋友们可以参考借鉴。
收藏 0 赞 0 分享

IOS绘制虚线的方法总结

这篇文章给大家分享了iOS中绘制虚线常见的几种方式,大家可以根据自己的需求进行选择哪种方法,下面跟着小编来一起看看吧。
收藏 0 赞 0 分享

React Native搭建iOS开发环境

React Native的门槛不管是对于前端开发者还是移动端开发者来说都是很高的,既要懂原生又要懂js,技术栈是相当长的。但是没有关系,下面我们一步步来学习,慢慢成长吧!
收藏 0 赞 0 分享

IOS轻松几步实现自定义转场动画

这篇文章将讲述几个步骤实现转场动画的自定义方式,并且给出了示例代码,毕竟代码才是我们的语言,这样比较容易上手。下面来一起看看吧。
收藏 0 赞 0 分享
查看更多