【问题标题】:How to render stretched text in iOS?如何在 iOS 中渲染拉伸文本?
【发布时间】:2011-07-12 03:34:22
【问题描述】:

给定一个矩形区域,我想使用特定字体渲染一些文本并让渲染的文本填充矩形。如下图:

  1. 这与仅更改字体大小不同
  2. 将其渲染为位图然后对其进行缩放不是一种选择(看起来很糟糕)
  3. 矢量图形就是这样做的方法

解决方案

我想出了以下似乎适合我的目的。该代码绘制单行文本缩放以填充边界。子类 UIView 并替换 drawRect 如下。

- (void)drawRect:(CGRect)rect 
{
    [self drawScaledString:@"Abcde"]; 
}

- (void)drawScaledString:(NSString *)string
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);

    NSAttributedString *attrString = [self generateAttributedString:string];

    CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attrString, CFRangeMake(0, string.length), 
                                   kCTForegroundColorAttributeName, [UIColor redColor].CGColor);

    CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef) attrString);

    // CTLineGetTypographicBounds doesn't give correct values, 
    // using GetImageBounds instead
    CGRect imageBounds = CTLineGetImageBounds(line, context);
    CGFloat width = imageBounds.size.width;
    CGFloat height = imageBounds.size.height;

    CGFloat padding = 0;

    width += padding;
    height += padding;

    float sx = self.bounds.size.width / width;
    float sy = self.bounds.size.height / height;

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);

    CGContextTranslateCTM(context, 1, self.bounds.size.height);
    CGContextScaleCTM(context, 1, -1);
    CGContextScaleCTM(context, sx, sy);

    CGContextSetTextPosition(context, -imageBounds.origin.x + padding/2, -imageBounds.origin.y + padding/2);

    CTLineDraw(line, context);
    CFRelease(line);
}

- (NSAttributedString *)generateAttributedString:(NSString *)string
{

    CTFontRef helv = CTFontCreateWithName(CFSTR("Helvetica-Bold"),20, NULL);
    CGColorRef color = [UIColor blackColor].CGColor;

    NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (id)helv, (NSString *)kCTFontAttributeName,
                                    color, (NSString *)kCTForegroundColorAttributeName,
                                    nil];

    NSAttributedString *attrString = [[[NSMutableAttributedString alloc]
                                   initWithString:string
                                        attributes:attributesDict] autorelease];

    return attrString;
}

示例用法:

CGRect rect = CGRectMake(0, 0, 50, 280);
MyCTLabel *label = [[MyCTLabel alloc] initWithFrame:rect];
label.backgroundColor = [UIColor whiteColor]; 
[self addSubview:label];

【问题讨论】:

  • 您在此处添加的解决方案不会为我生成任何可见的渲染文本。当我开始一个简单的项目时,添加 CoreText(和 QuartzCore 以获得良好的衡量标准)然后创建一个名为 MyCTLabel 的 UIView 子类(再次,作为良好的衡量标准),然后将其作为子视图添加到我的视图控制器的视图中,我得到了一个瘦的没有文字的窄白色列。增加视图的矩形大小对文本的可见性没有影响......有什么想法吗?
  • 为我工作,在 iOS 6.1 和 9.3 上测试,谢谢!
  • 嘿@Martin 你找到解决这个问题的方法了吗,直到现在我找不到一个例子来做到这一点。如果您知道,请在此处分享示例代码。谢谢

标签: iphone ios fonts core-graphics uilabel


【解决方案1】:

可以设置 UILabel 变换属性并缩放宽度:

[myLabel sizeToFit];
myLabel.transform = CGAffineTransformMakeScale(0.5, 1.0);

【讨论】:

  • 我试过了,但结果是文本被渲染然后缩放为位图,这还不够好,不幸的是。
【解决方案2】:

你可以试试 CoreText。获取CTFramesetter,计算其矩形,然后计算将该矩形压缩到所需边界所需的仿射变换并将其设置为 CTM。然后,当您绘制文本时,它应该以完整的质量适当地拉伸它。

【讨论】:

  • 我查看了 CT 文档,但我不清楚如何按照您所说的去做。苹果的例子没有多大帮助。然而,我确实设法在 Quartz 2D 中渲染拉伸文本,但这迫使我手动进行布局管理(文本换行等)。关于使用 CT、示例或其他内容,您还有什么要说的吗?
  • @Martin:我不知道在哪里可以找到一个好的例子。您需要创建一个CTFramesetterRef 对象,您可以使用它来绘制文本。您还需要在绘制文本之前翻转坐标系,因为 CoreText 使用与 UIView 相反的坐标系。
  • 我将此标记为正确答案。 CT 严重缺乏文档和示例,但由于这个答案,我最终得到了它。
【解决方案3】:

你也可以试试UILabel的@property(nonatomic) BOOL adjustsFontSizeToFitWidth@property minimumFontSize

最初,您可以为字体属性设置更高的值,并使用最小字体值初始化minimumFontSize

【讨论】:

  • 谢谢,但本质上只是改变字体大小,并不能解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
  • 2015-06-18
相关资源
最近更新 更多