【问题标题】:Is it possible to alter the letter-spacing/kerning of a font with Cocoa Touch?是否可以使用 Cocoa Touch 更改字体的字母间距/字距?
【发布时间】:2010-11-06 23:44:35
【问题描述】:

我已经在互联网上搜索了一段时间,以获取有关如何在 UIKit 中更改字体的字母间距/字距调整的信息。

我担心的是,就像使用您自己的自定义字体一样,您根本做不到。这将是一个可怕的消息。

我知道 Apple 正在保护我们免受这些限制的不良设计的影响,但它们也阻止我们实施真正伟大的设计。

人们建议我做什么?

  1. 使用带有标准字距的字体,人们可能不会注意到差异。

  2. 找到某人的 hacked 课程,以获得用户在付出辛苦赚来的现金后应得的外观。

  3. 使用我不知何故忽略的方法,并使用 UIKit 来做,向传授这些隐藏知识的人表示我永远的感激之情。

【问题讨论】:

  • 实际上有很多方法可以在 iPhone 上加载字体(尽管没有一个公共 API 方法实际上暴露了 UIFont):stackoverflow.com/questions/360751/…
  • 我希望 Apple 能够跟上 CSS。

标签: iphone objective-c cocoa-touch core-graphics quartz-graphics


【解决方案1】:

接受的答案丢失了很多格式,user363349 的答案主要对我有用,但文本对齐不起作用。我修改了代码来解决这个问题:

- (void) drawRect:(CGRect)rect
{
    // Drawing code
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSelectFont (context, [self.font.fontName cStringUsingEncoding:NSASCIIStringEncoding], self.font.pointSize, kCGEncodingMacRoman);
    CGContextSetCharacterSpacing(context, characterSpacing);
    CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
    CGAffineTransform myTextTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1.f, -1.f );

    CGContextSetTextMatrix (context, myTextTransform);

    // draw 1 but invisbly to get the string length.
    CGPoint p =CGContextGetTextPosition(context);
    float centeredY = (self.font.pointSize + (self.frame.size.height- self.font.pointSize)/2)-2;
    CGContextShowTextAtPoint(context, 0, centeredY, [self.text cStringUsingEncoding:NSASCIIStringEncoding], [self.text length]);
    CGPoint v =CGContextGetTextPosition(context);

    // calculate width and draw second one.
    float width = v.x - p.x;
    float destX = 0;

    // calculate X position based on alignment
    if([self textAlignment] == UITextAlignmentLeft){
        destX = 0;
    }else if([self textAlignment] == UITextAlignmentCenter){
        destX = (self.frame.size.width- width)/2;
    }else if([self textAlignment] == UITextAlignmentRight){
        destX = self.frame.size.width - width;
    }
    CGContextSetFillColorWithColor(context, [self.textColor CGColor]);
    CGContextShowTextAtPoint(context, destX, centeredY, [self.text cStringUsingEncoding:NSASCIIStringEncoding], [self.text length]);
}

【讨论】:

  • 很好,保持对齐是一个很好的补充!
【解决方案2】:

我从 Google 来到这里,试图对 UITextField 做同样的事情。我在下面实现了一些对 UILabel 通用的东西。

@interface AdjustableUILable : UILabel {
    CGFloat characterSpacing;
}

@property CGFloat characterSpacing;

@end


@implementation AdjustableUILable

@synthesize characterSpacing;

- (void)drawTextInRect:(CGRect)rect
{    
    if (characterSpacing)
    {
        // Drawing code
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGFloat size = self.font.pointSize;

        CGContextSelectFont (context, [self.font.fontName UTF8String], size, kCGEncodingMacRoman);
        CGContextSetCharacterSpacing (context, characterSpacing);
        CGContextSetTextDrawingMode (context, kCGTextFill);

        // Rotate text to not be upside down
        CGAffineTransform xform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
        CGContextSetTextMatrix(context, xform);
        const char *cStr = [self.text UTF8String];
        CGContextShowTextAtPoint (context, rect.origin.x, rect.origin.y + size, cStr, strlen(cStr));
    }
    else
    {
        // no character spacing provided so do normal drawing
        [super drawTextInRect:rect];
    }
}

@end

然后要使用它,只要在viewDidLoad里设置标签什么的

- (void)viewDidLoad
{
        myLabel.characterSpacing = 2; // point size
}

我用 UITextField 尝试过,但不幸的是,它只是在用户编辑字段后才添加字符间距。 -drawTextInRect 仅在 -textFieldShouldEndEditing 委托方法之后调用。来自其他论坛的一些人建议这是因为 UITextField 需要知道字体的渲染才能显示光标。从来没有为那件作品找到解决方案...

【讨论】:

    【解决方案3】:

    您可以使用 Quartz 2D 完成您需要的操作。具体来说,CGContextSetCharacterSpacing 属性可以控制字母之间的间距。不过我不确定字距调整。

    Quartz 2D Programming Guide: Text

    【讨论】:

      【解决方案4】:

      我已扩展 UILabel 以更改字符间距。这应该可以解决问题,并从 UILabel 本身中提取字体、文本、颜色等(正确编码!)。

      你可能会注意到我画了两次文字,第一次是用清晰的颜色。这是为了使标签中的文本自动居中。虽然这可能效率低下 - 自动居中不是很好吗?

      享受吧!

      @interface RALabel : UILabel {
      }
      @end  
      
      @implementation RALabel 
      
      - (void) drawRect:(CGRect)rect 
      {
      
          // Drawing code
      
          CGContextRef context = UIGraphicsGetCurrentContext();
          CGContextSelectFont (context, [self.font.fontName cStringUsingEncoding:NSASCIIStringEncoding], self.font.pointSize, kCGEncodingMacRoman);
          CGContextSetCharacterSpacing(context, 1);
          CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
          CGAffineTransform myTextTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1.f, -1.f );
          CGContextSetTextMatrix (context, myTextTransform);
      
          // draw 1 but invisbly to get the string length.
          CGPoint p =CGContextGetTextPosition(context);
          float centeredY = (self.font.pointSize + (self.frame.size.height- self.font.pointSize)/2)-2;
          CGContextShowTextAtPoint(context, 0, centeredY, [self.text cStringUsingEncoding:NSASCIIStringEncoding], [self.text length]);
          CGPoint v =CGContextGetTextPosition(context);
      
          // calculate width and draw second one.
          float width = v.x - p.x;
          float centeredX =(self.frame.size.width- width)/2;
          CGContextSetFillColorWithColor(context, [self.textColor CGColor]);
          CGContextShowTextAtPoint(context, centeredX, centeredY, [self.text cStringUsingEncoding:NSASCIIStringEncoding], [self.text length]);
      
      }
      

      【讨论】:

        【解决方案5】:

        CGContextShowText 方法的主要问题 - 它们只是 ASCII 字符串的显示。 要显示 UTF 字符串,您需要将字符串符号映射到字形并显示字形。

            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSelectFont (context, [self.font.fontName cStringUsingEncoding:NSASCIIStringEncoding], self.font.pointSize, kCGEncodingMacRoman);
            CGContextSetCharacterSpacing(context, characterSpacing);
            CGContextSetFillColorWithColor(context, [self.textColor CGColor]);
            CGAffineTransform myTextTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1.f, -1.f );
            CGContextSetTextMatrix (context, myTextTransform);
        
            CGGlyph glyphs[self.text.length];
            CTFontRef fontRef = CTFontCreateWithName((CFStringRef)self.font.fontName, self.font.pointSize, NULL);
            CTFontGetGlyphsForCharacters(fontRef, (const unichar*)[self.text cStringUsingEncoding:NSUnicodeStringEncoding], glyphs, self.text.length);
            float centeredY = (self.font.pointSize + (self.frame.size.height- self.font.pointSize)/2)-2;
            CGContextShowGlyphsAtPoint(context, rect.origin.x, centeredY, (const CGGlyph *)glyphs, self.text.length);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-11
          • 2023-03-21
          • 2013-04-21
          • 2012-11-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多