Подтвердить что ты не робот

Можно ли изменить буквенный интервал/кернирование шрифта с помощью Cocoa Touch?

Я некоторое время чистил интернет для получения информации о том, как можно изменить буквенное расстояние/кернирование шрифта внутри UIKit.

Мой страх в том, что, как и использование ваших собственных пользовательских шрифтов, вы просто не можете. Что было бы ужасно.

Я знаю, что Apple защищает нас от плохого дизайна с этими ограничениями, но они также мешают нам реализовать действительно отличный дизайн.

Что люди предлагают мне делать?

  • Используйте шрифт со стандартным кернинг, люди, вероятно, не заметили бы разницу.

  • Найдите кого-то взломанного класса, чтобы получить тот взгляд, которого заслуживает пользователь после расставания с их с трудом заработанные деньги.

  • Используйте метод, который я как-то упустил, и сделайте это с UIKit, пообещав мою вечную благодарность человеку, который передает этот скрытый самородк знаний.

4b9b3361

Ответ 1

Я приземлился здесь из 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 должен знать визуализацию шрифта для отображения курсора. Никогда не нашел решение для этой части...

Ответ 2

Принятый ответ потерял много форматирования, и ответ 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]);
}

Ответ 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);