CTFrameGetLineOrigins错误
似乎还有其他人有这个问题,但我还没有找到解决办法。 我正在尝试创建一个高亮背景的UILabel,与OS X中桌面文件下面的标签完全相同,如下所示:
我决定用CoreText来解决这个问题,而且我偶然发现了一个我似乎无法解决的错误:
-drawRect方法
在我的UILabel的drawRect方法中,我使用CoreText将文本绘制到屏幕上,然后为绘制的每一行文本创建一个UIBezierPath。 (该标签永远不会超过两行)
CGContext context = UIGraphicsGetCurrentContext();
/* Flip coordinate plane */
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, self.bounds);
NSAttributedString *attributedText = [self attributedText]; /* [self attributedText] returns an NSAttributedString formatted with font, linebreak, and alignment. */
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedText);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attributedText length]), path, NULL);
CFArrayRef lines = CTFrameGetLines(frame);
CGPoint *lineOrigins = malloc(CFArrayGetCount(lines));
CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins); //<------
/* Get frame for line 1 */
CTLineRef line1 = CFArrayGetValueAtIndex(lines, 0);
CGRect lineFrame = CTLineGetImageBounds(line1, context);
CGPoint lineFrameOrigin = CGPointMake(lineOrigins[0].x, self.bounds.size.height - lineOrigins[0].y);//Coordinates flipped once again
lineFrame.origin = lineFrameOrigin;
UIBezierPath *linePath = [UIBezierPath bezierPathWithRoundedRect:lineFrame cornerRadius:0];
[self.path appendPath:linePath];
/* Repeat for line 2 */
CTFrameDraw(frame, context);//Draw the text.
在为每一行获得CGRect后,将它放入UIBezierPath中,然后通过-appendPath
方法将其与其他行的路径合并。 从路径制作图层蒙版,并将标签的背景颜色更改为蓝色。
问题
奇怪的是,这是上面的代码的输出:
面具位于太远,我不知道为什么。 看起来CTFrameGetLineOrigins
函数正在返回一个不正确的y值。
通过添加下面的代码行:
lineFrameOrigin.y -= self.font.leading / 2;
结果得到改善:
但是,它在y轴上似乎仍然过低。 我相信上面的这条线只是一个巧合,这个值恰好接近正确的y值。
无论如何,因为我知道这个问题之前已经被问过了,有没有其他方法可以实现这个目标? 这个奇怪的bug有没有新的信息? 我为什么函数的值被关闭了,我感到很惊讶。
我会做这样的事情来得到直线:
CTFrameRef frame;
CFArrayRef lines = CTFrameGetLines(frame);
CFIndex numLines = CFArrayGetCount(lines);
CTLineRef line1 = (CTLineRef)CFArrayGetValueAtIndex(lines, 0);
CGPoint *origins = (CGPoint *)malloc(numLines * sizeof(CGPoint));
CTFrameGetLineOrigins(self.ctFrame, CFRangeMake(0, 0), origins);
CGPoint origin = origins[0];
CGFloat ascent, descent, leading;
CTLineGetTypographicBounds(line1, &ascent, &descent, &leading);
CFRange lineRange = CTLineGetStringRange(line1);
CGFloat lineStart = CTLineGetOffsetForStringIndex(line1, lineRange.location, NULL);
CGFloat lineEnd = CTLineGetOffsetForStringIndex(line1, CFRangeMaxRange(lineRange), NULL);
CGRect box = CGPathGetBoundingBox(CTFrameGetPath(frame));
CGFloat lineHeight = ascent + descent + leading;
CGFloat rectX = box.origin.x + origin.x + lineStart;
CGFloat rectY = box.origin.y + origin.y - lineHeight;
CGRect rectForLine = CGRectMake( rectX, rectY, lineEnd - lineStart, lineHeight);
我更喜欢在图像边界上获得印刷边界。 我认为你需要上升,体面和导致获得起源。 我也总是偏离帧起源,但你可能不需要。
链接地址: http://www.djcxy.com/p/14379.html