是否可以使用Cocoa Touch更改字体的字母间距/字距调整?

时间:2009-06-30 11:58:11

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

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

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

我知道Apple正在通过这些限制来保护我们免受糟糕的设计,但它们也阻止我们实现真正优秀的设计。

人们建议我做什么?

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

  2. 找到某人的黑客入门课程,以便在用辛苦赚来的现金分手后获得用户应得的外观。

  3. 使用我忽略的方法,并与UIKit一起做这件事,向那个传授这隐藏知识的人承诺我永远的感激。

5 个答案:

答案 0 :(得分:4)

我从谷歌到这里试图用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需要知道字体的渲染才能显示光标。从来没有找到解决方案......

答案 1 :(得分:4)

接受的答案丢失了很多格式,而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 :(得分:3)

您可以使用Quartz 2D完成所需的操作。具体来说,CGContextSetCharacterSpacing属性可以控制字母之间的间距。虽然我不确定是否会做错。

Quartz 2D Programming Guide: Text

答案 3 :(得分:3)

我扩展了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]);

}

答案 4 :(得分:1)

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