Рисование одного NSString с двумя разными шрифтами в drawRect?

У меня есть одна строка в качестве экземпляра var, и я хочу нарисовать ее двумя разными шрифтами по частям. если быть точным, это выглядит так: xyz(abc) .

то есть: я хочу нарисовать часть «xyz()» обычным шрифтом и «abc» курсивом.

Эта строка является свойством, а представление является общим. Только в конкретном случае должна отображаться такая строка.

Я попробовал NSAttributedString и его версию Mutable, но, похоже, она не полностью поддерживается на iOS.

Не удалось получить ключи для атрибутов. Что мне делать?

Можно ли здесь использовать NSAttributedString?


person Amogh Talpallikar    schedule 04.05.2012    source источник


Ответы (3)


Я бы подклассировал UIView для рисования с использованием основного текста и передал бы ему настроенную строку NSAttributed,

У меня в голове что-то вроде этого:

CustomLabel.h
#import <CoreText/CoreText.h>

@interface CustomLabel : UIView
@property NSAttributedString *attributedText;
@end

CustomLabel.m

@interface SMAttributedTextView ()
{
    @protected
    CTFramesetterRef _framesetter;
}

@implementation SMAttributedTextView

@synthesize attributedString = _attributedString;
    //need dealloc even with ARC method to release framesetter if it still exists
- (void)dealloc{
    if (_framesetter) CFRelease(_framesetter);
}

- (void)setAttributedString:(NSAttributedString *)aString
{
    _attributedString = aString;
    [self setNeedsDisplay];//force redraw
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    //Context Drawing Setup
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.frame.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextSetShouldSubpixelPositionFonts(context, YES);
    CGContextSetShouldSubpixelQuantizeFonts(context, YES);
    CGContextSetShouldAntialias(context, YES);

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, rect);

    CTFramesetterRef framesetter = [self framesetter];
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [_attributedText length]), path, NULL);
    CTFrameDraw(frame, context);
    CFRelease(frame);
    CFRelease(path);

    UIGraphicsPushContext(context);
}

@end

поэтому вне этого вы должны вызвать установщик для атрибутированной строки, и она должна перерисовываться. вы также примените пользовательские черты к диапазонам строки NSAttributd ДО того, как отправите ее в представление. Вы можете использовать регулярное выражение или просто поиск по общей строке, чтобы найти его.

i.e

NSMutableAttributedString *aString = [[NSMutableAttributedString alloc] initWithString:@"xyz(abc)"];
NSRange rangeOfABC = NSMakeRange(4,3);
//make style dictionary **see core text docs - I can't remeber off the top of my head sorry
[aString addAttributes:newAttrs range:rangeOfABC];

[customlabel setAttributedString:aString];

с точки зрения кода это может немного отличаться - я на своей нерабочей машине, извините, поэтому не могу проверить это на 100%,

также по памяти так вы можете применить курсив к текущему шрифту атрибутированной строки

NSString *targetString = @"xyc(abc)";
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:targetString];
NSRange entireRange = NSMakeRange(0, (targetString.length -1));
NSDictionary *attDict = [attString attributesAtIndex:entireRange.location effectiveRange:&entireRange];
CTFontRef curFontRef = (__bridge CTFontRef)[attDict objectForKey:@"NSFont"];
CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(curFontRef);
BOOL isItalic = ((traits & kCTFontItalicTrait) == kCTFontItalicTrait);

NSMutableDictionary *newAttrs = [NSMutableDictionary dictionary];
CTFontRef italicRef = CTFontCreateCopyWithSymbolicTraits(curFontRef,
                                                         CTFontGetSize(curFontRef),
                                                         NULL,
                                                         kCTFontItalicTrait,
                                                         kCTFontItalicTrait);

if (italicRef)
{
    newAttrs = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)italicRef, kCTFontAttributeName,nil];
    [attString addAttributes:newAttrs range:NSMakeRange(4,3)];//or whatever range you want
    CFRelease(italicRef);
}

Надеюсь, поможет.

person fatuous.logic    schedule 04.05.2012

Я думаю, вам нужно использовать две разные строки/метки для достижения этого эффекта. Насколько я знаю, это невозможно сделать, используя только метку или другой подобный элемент.

Я также использовал веб-просмотры в подобных ситуациях и использовал html/css для отображения частей одного текста с разными стилями.

person BBog    schedule 04.05.2012

Вы должны предоставить свой собственный элемент управления для рисования NSAttributedString, например TTTAttributedLabel.

person Community    schedule 04.05.2012