CoreText手动换行:如何定位文本,垂直对齐?

时间:2012-05-17 06:25:58

标签: iphone ios uilabel core-text


我正在尝试创建一个自定义标签子类,它绘制富文本,我可以在其中设置不同的参数。我有一个最重要的要求是断线。在UILabel中是固定的,有时它不符合图形要求 因此,帮助自己在Apple网站上获得一些小片段,我已经开始编写自己的课程,并且它可以工作(不知何故),但我遇到了一个问题:

  1. 如果该行只有一行,则文本不会垂直对齐,而是始终从屏幕的左上角开始
  2. 这是我到目前为止编写的代码:

    - (void)drawRect:(CGRect)rect
    {
        if (_text) {
    
            if (!_attribstring) {
                [self createAttributedString];
            }
            if (self.lineBreakValue == 0) {
                self.lineBreakValue = 9;
            }
    
            CGContextRef ctx = UIGraphicsGetCurrentContext();
            CGContextTranslateCTM(ctx, 0, self.bounds.size.height);
            CGContextScaleCTM(ctx, 1.0, -1.0); 
            CGContextSetShouldSmoothFonts(ctx, YES);
            CGContextSetShouldAntialias(ctx, YES);
            CGRect textRect = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
    
            //Manual Line braking
            BOOL shouldDrawAnotherLine = YES;
            double width = textRect.size.width;
            CGPoint textPosition = CGPointMake(textRect.origin.x, textRect.origin.y+textRect.size.height-self.lineBreakValue);
            ;
            // Initialize those variables.
    
            // Create a typesetter using the attributed string.
            CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedString((__bridge CFAttributedStringRef )  self.attribstring);
    
            // Find a break for line from the beginning of the string to the given width.
            CFIndex start = 0;
            while (shouldDrawAnotherLine) {
    
                CFIndex count = CTTypesetterSuggestLineBreak(typesetter, start, width);
    
                // Use the returned character count (to the break) to create the line.
                CTLineRef line = CTTypesetterCreateLine(typesetter, CFRangeMake(start, count));
    
                // Get the offset needed to center the line.
                float flush = 0.5; // centered
                double penOffset = CTLineGetPenOffsetForFlush(line, flush, width);
    
                // Move the given text drawing position by the calculated offset and draw the line.
                CGContextSetTextPosition(ctx, textPosition.x + penOffset, textPosition.y);
                CTLineDraw(line, ctx);
                if (line!=NULL) {
                    CFRelease(line);
                }
                // Move the index beyond the line break.
    
                if (start + count >= [self.attribstring.string length]) {
                    shouldDrawAnotherLine = NO;
                    continue;
                }
                start += count;
                textPosition.y-=self.lineBreakValue;
            }
            if (typesetter!=NULL) {
                CFRelease(typesetter);
    
            }
    
        }
    
    }
    

    有人能指出我正确的方向吗? 问候,
    安德烈

1 个答案:

答案 0 :(得分:1)

要垂直对齐布局文本,您需要知道线条的总高度,第一行的y position为:

(self.bounds.size.height - (totalLineHeight)) / 2 - font.ascent;

所以你需要在你的代码中使用2个循环,一个用于计算行的总高度(你也可以保存每行的字数,以便以后在另一个循环中用于绘图),另一个肯定用于绘制从y position使用上述公式计算。

注意:每行的高度可以是字体大小,也可以在行之间添加行间距,所有你需要确保的是在计算行高时保持一致并根据{{1}绘制这些行}。