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

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

效果:

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

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

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

(0)

相关推荐

  • iOS利用NSAttributedString实现图文混排效果示例

    前言 NSAttributedString 可以非常方便的实现文字排版和图文混排功能,UILabel 和 UITextView 都能添加 NSAttributedString 属性字符串,通过这一点,可以实现带有属性的文字和文字内包含图片的文本内容展示.话不多说了,下面来一起看看详细的介绍吧. 效果如下: 示例代码如下: 1-初始化可变属性字符串 NSMutableAttributedString *attributedString = [[NSMutableAttributedString a

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

    IOS 图文混排(CoreText.framework)        本文主要介绍了IOS图文混排的资料,这里整理了在网上查找的内容,帮助理解,掌握这部分知识,以下就是整理的内容: 利用CORETEXT进行图文混排. 实现代码: void RunDelegateDeallocCallback( void* refCon ){ } CGFloat RunDelegateGetAscentCallback( void *refCon ){ NSString *imageName = (NSStri

  • IOS 指纹识别两种方式详解及实例

    IOS 指纹识别两种方式详解及实例 首先引入类名: #import <LocalAuthentication/LocalAuthentication.h> 然后在实现指纹识别的地方放入如下代码: 方式一: LAContext *lacontext = [[LAContext alloc]init]; // 判断设备是否支持指纹识别 BOOL isSupport = [lacontext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWit

  • IOS点击按钮隐藏状态栏详解及实例代码

    IOS点击按钮隐藏状态栏详解 前言: 最近学习IOS的基础知识,实现隐藏状态栏的功能,这里就记录下来,希望对大家有所帮助 实例代码: @interface SecondViewController () @property (nonatomic, assign,getter=isHideStatus) BOOL hideStatus; @end @implementation SecondViewController - (void)viewDidLoad { [super viewDidLoa

  • iOS指纹登录(TouchID)集成方案详解

    TouchID指纹识别是iPhone 5S设备中增加的一项重大功能.苹果的后续移动设备也相继添加了指纹功能,在实际使用中还是相当方便的,比如快捷登录,快捷支付等等.系统提供了相应框架,使用起来还是比较方便的.使用LAContext对象即可完成指纹识别,提高用户体验. 提示:指纹识别必须用真机测试,并且在iOS8以上系统. TouchID API使用 1.添加头文件 #import 2.判断系统版本 //首先判断版本 if (NSFoundationVersionNumber < NSFounda

  • 详解Android SpannableString多行图文混排的应用实战

    TeXtView大家应该都不陌生,文本展示控件嘛! 就用TextView显示普普通通的文本,OK,很简单,Android入门的都会,没入门的在门缝外看两眼也都会,哈哈,开玩笑.那要是设计在开发需求中要求类似微信聊天表情一样在TextView中插入表情图片呢? 有的小伙伴就会说啦,"TextView添加图片我会啊,不就是drawableLeft,drawableRight嘛!" 嗯 ~ 也行,算是一种方法,可这有一个限制,首先,图片只能在TextView的两端,其次,两端都只能设置一张图

  • 集合框架(Collections Framework)详解及代码示例

    简介 集合和数组的区别: 数组存储基础数据类型,且每一个数组都只能存储一种数据类型的数据,空间不可变. 集合存储对象,一个集合中可以存储多种类型的对象.空间可变. 严格地说,集合是存储对象的引用,每个对象都称为集合的元素.根据存储时数据结构的不同,分为几类集合.但对象不管存储到什么类型的集合中,既然集合能存储任何类型的对象,这些对象在存储时都必须向上转型为Object类型,也就是说,集合中的元素都是Object类型的对象. 既然是集合,无论分为几类,它都有集合的共性,也就是说虽然存储时数据结构不

  • ios电子书翻页效果代码详解

    近实现了一个完整的电子书阅读器,支持txt和epub格式的电子书阅读,其中epub支持图文混排的方式展示.本文主要谈谈其中两种翻页效果的实现,分别为仿真翻页和水平滑动翻页. 仿真翻页 最合适的方案就是使用系统提供的UIPageviewcontroller了,不过默认的UIpageviewcontroller翻页时背面是白色的,而阅读器通常都会有背景色或背景图片,翻页时用户体验就很糟糕,比如就像下面这样 所以接下来主要说说如何修改背面颜色以达到美观的翻页效果. UIpageviewcontroll

  • Android中使用TextView实现图文混排的方法

    向TextView或EditText中添加图像比直接添加文本复杂一点点,需要用到<img>标签. <img>只有一个src属性,该属性原则上应该指向一个图像地址或可以找到某个图像资源的唯一标识.但要注意的是,系统并不会直接根据src属性所指的值自动获取和显示图像,这一切都需要我们去做.说白了,src属性指的是什么只有开发者自己知道.开发者需要告诉系统src属性到底指的是什么,然后系统才会知道怎么做. 解析src属性值需要ImageGetter对象的getDrawable方法来完成.

  • IOS Swift基础之switch用法详解

    IOS  Swift基础之switch用法详解 概述 Swift中的switch语句与Java等语言中的switch有很大的相似点,但是也有不同的地方,并且更加灵活. Swift中switch的case语句中不需要添加break Swift中需要考虑所有情况,default是必要的. case分支可以添加多个条件,用,分割 case不局限与常量,可以使使用范围 switch里可以使用元组 switch默认不需要添加break,执行一个case之后就跳出语句,如果想要继续下面的语句可以使用fall

随机推荐