IOS 圖文混排(CoreText.framework)詳解及實例
IOS 圖文混排(CoreText.framework)
本文主要介紹了IOS圖文混排的資料,這里整理了在網(wǎng)上查找的內(nèi)容,幫助理解,掌握這部分知識,以下就是整理的內(nèi)容:
利用CORETEXT進行圖文混排。
實現(xiàn)代碼:
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; }
先設(shè)置一個CTRun的委托,主要是用于指定對象的上行高,寬,或上下文釋放時使用。
-(void)drawCharAndPicture { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetTextMatrix(context, CGAffineTransformIdentity);//設(shè)置字形變換矩陣為CGAffineTransformIdentity,也就是說每一個字形都不做圖形變換 CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height); CGContextConcatCTM(context, flipVertical);//將當(dāng)前context的坐標(biāo)系進行flip NSLog(@"bh=%f",self.bounds.size.height); NSMutableAttributedString *attributedString = [[[NSMutableAttributedString alloc] initWithString:@"請在這里插入一張圖片位置"] autorelease]; //為圖片設(shè)置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); }
效果:
從上面看大家可能沒有發(fā)現(xiàn)什么問題,當(dāng)把圖片放在字的最左邊會是什么樣子的?
因此為了避免這種情況發(fā)生,我在代碼中添加了換行模式。添加換行后的效果:
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
HTTP/2 協(xié)議用于 iOS 推送提醒服務(wù) (APNS)
基于JSON的請求和響應(yīng)對于每個通知,如果成功響應(yīng),將會返回200標(biāo)識 - 不用再去猜測通知是否被接收到響應(yīng)錯誤將會以JSON字符消息的長度從2048個字節(jié)增加到4096個字節(jié)連接狀態(tài)可以通過HTTP/2的ping框架來進行檢查.2016-04-04iOS中模態(tài)Model視圖跳轉(zhuǎn)和Push視圖跳轉(zhuǎn)的需求實現(xiàn)方法
這篇文章主要介紹了iOS中模態(tài)Model視圖跳轉(zhuǎn)和Push視圖跳轉(zhuǎn)的需求實現(xiàn),非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-12-12iOS runtime forwardInvocation詳解及整理
這篇文章主要介紹了 iOS runtime forwardInvocation詳解及整理的相關(guān)資料,需要的朋友可以參考下2017-02-02iOScollectionView廣告無限滾動實例(Swift實現(xiàn))
本篇文章主要介紹了iOScollectionView廣告無限滾動實例,可以實現(xiàn)廣告無限滾動,有興趣的可以了解一下。2016-11-11iOS應(yīng)用開發(fā)中的文字選中操作控件UITextView用法講解
這篇文章主要介紹了iOS應(yīng)用開發(fā)中的文字選中操作控件UITextView用法講解,代碼基于傳統(tǒng)的Objective-C語言,需要的朋友可以參考下2016-02-02