2015-03-13 57 views
2

编辑:Here's a Github Gist如果这是更具可读性的代码。核心文本中的垂直文本对齐

我正在写一个方法来使用核心文本在PDF中的矩形内绘制文本。我写的东西完成了我所需要的一切,除了垂直对齐(顶部,中间,底部)。目前正在绘制文本的标准方式是顶部,我特别需要底部对齐。

- (void)drawText:(NSString *)textToDraw inFrame:(CGRect)frameRect withFont:(UIFont *)originalFont textColor:(UIColor *)textColor alignment:(PDFTextAlignment)alignment verticalAlignment:(PDFTextVerticalAlignment)verticalAlignment { 

    if (!textToDraw) { 
     // If nil, give it an empty value to draw 
     textToDraw = @""; 
    } 


    // Prepare font 
    CTFontRef font = [self ctFontRefFromUIFont:originalFont]; 
    CGColorRef color = textColor.CGColor; 

    // Paragraph 
    CTTextAlignment ctAlignment; 
    switch (alignment) { 
     case PDFTextAlignmentLeft: 
      ctAlignment = kCTTextAlignmentLeft; 
      break; 
     case PDFTextAlignmentCenter: 
      ctAlignment = kCTTextAlignmentCenter; 
      break; 
     case PDFTextAlignmentRight: 
      ctAlignment = kCTTextAlignmentRight; 
      break; 
     case PDFTextAlignmentJustified: 
      ctAlignment = kCTTextAlignmentJustified; 
      break; 
     default: 
      ctAlignment = kCTTextAlignmentLeft; 
      break; 
    } 

    CTParagraphStyleSetting settings[] = { 
    {kCTParagraphStyleSpecifierAlignment, sizeof(ctAlignment), &ctAlignment}, 
    }; 

    CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings)/sizeof(settings[0])); 

    // Create an attributed string 
    CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName, kCTParagraphStyleAttributeName }; 
    CFTypeRef values[] = { font, color, paragraphStyle }; 
    CFDictionaryRef attr = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values, 
              sizeof(keys)/sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 

    CFStringRef stringRef = (__bridge CFStringRef)textToDraw; 
    // Prepare the text using a Core Text Framesetter. 
    CFAttributedStringRef currentText = CFAttributedStringCreate(NULL, stringRef, attr); 

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText); 

    CGMutablePathRef framePath = CGPathCreateMutable();  

    CGPathAddRect(framePath, NULL, frameRect); 

    // Get the frame that will do the rendering. 
    CFRange currentRange = CFRangeMake(0, 0); 
    CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL); 
    CGPathRelease(framePath); 

    // Get the graphics context. 
    CGContextRef currentContext = UIGraphicsGetCurrentContext(); 

    // Put the text matrix into a known state. This ensures 
    // that no old scaling factors are left in place. 
    CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity); 

    // Core Text draws from the bottom-left corner up, so flip 
    // the current transform prior to drawing. 
    // Modify this to take into consideration the origin. 
    CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2); 
    CGContextScaleCTM(currentContext, 1.0, -1.0); 

    // Draw the frame. 
    CTFrameDraw(frameRef, currentContext); 

    // Add these two lines to reverse the earlier transformation. 
    CGContextScaleCTM(currentContext, 1.0, -1.0); 
    CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2); 

    CFRelease(frameRef); 
    CFRelease(stringRef); 
    CFRelease(framesetter); 
    CFRelease(font); 
    CFRelease(paragraphStyle); 
} 

下面是如何将目前在矩形绘制文本的例子(注意与线绘制的矩形是我传递在同一frameRect)... enter image description here。 我希望这个文本显示为在这个矩形中的底部对齐,像这样... enter image description here

我已经通过this SO post的解决方案,但没有任何运气让文本正确对齐。

我传递了垂直对齐的枚举值,所以理想情况下我将使用以下条件确定垂直对齐。

if (verticalAlignment == PDFTextVerticalAlignmentTop) { 
    // Top align 
} else if (verticalAlignment == PDFTextVerticalAlignmentCenter) { 
    // Center (vertical) align 
} else if (verticalAlignment == PDFTextVerticalAlignmentBottom) { 
    // Bottom align 
} else { 
    // Default: Bottom alignment 
} 

谢谢!

回答

3

因为我不太清楚你是如何从链接文章中找到解决方案的,我会根据其中一个答案提出解决方案。这可能正是你所尝试的,但它也可能是适当的解决方案。

我假设存在一种获取CTFrameRef大小的方法,只要返回适当的CGSize,就将该实现留给您。除了链接的SO帖子中显示的方法之外,还可能需要查看CTFramesetterSuggestFrameSizeWithConstraints。假设这个功能是可用的,它应该是足够的调整绘图功能

... 
CGMutablePathRef framePath = CGPathCreateMutable();  

// Get the graphics context. 
CGContextRef currentContext = UIGraphicsGetCurrentContext(); 

CGRect textRect = frameRect; // Will also give you the default behavior for top align 
CGSize textSize = [self measureFrame:frameref forContext:currentContext]; 

if (verticalAlignment == PDFTextVerticalAlignmentBottom) { 
    // Bottom align 
    textRect.size.height = textSize.height; 
    textRect.origin.y = frameRect.origin.y + frameRect.size.height - textSize.height; 
} else if (verticalAlignment == PDFTextVerticalAlignmentCenter) { 
    // Center (vertical) align 
    textRect.size.height = textSize.height; 
    textRect.origin.y = frameRect.origin.y + (frameRect.size.height - textSize.height)/2; 
} 

CGPathAddRect(framePath, NULL, textRect); 
... 
+0

呀,最后我写的东西非常接近这个的这一部分,采用NSAtrributedString来获取文本框矩形的大小。我会与本周晚些时候回到这个项目时写的相比,同时感谢并享受赏金! – timgcarlson 2015-03-22 22:48:34