1


我正在尝试创建一个自定义标签子类来绘制富文本并且我可以在其中设置不同的参数。我最大的要求之一是关于换行。在 UILabel 中是固定的,有时它不符合图形要求。
因此,在 Apple 网站上帮助自己编写了一个小片段,我开始编写自己的课程,并且它(以某种方式)有效,但我遇到了一个问题:

  1. 如果只有一行,文本不垂直对齐,它总是从屏幕的左上角开始

这是我到目前为止编写的代码:

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

        }

    }

}

有人可以指出我正确的方向吗?问候,
安德里亚

4

1 回答 1

1

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

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

因此,您的代码中需要 2 个循环,一个用于计算线条的总高度(您还可以保存每条线的字符数以供以后在另一个循环中用于绘图),另一个肯定用于从使用y position计算的开始绘制线条上式。

注意:每行的高度可以是字体大小,也可以在行与行之间添加行间距,您需要确保在计算行高和绘制这些行时保持一致y position

于 2012-05-18T01:33:24.657 回答