iphone / ipad: как именно использовать NSAttributedString?


102

Да, многие люди говорят о Rich Text в iPhone / iPad, и многие знают об этом NSAttributedString.

Но как пользоваться NSAttributedString? Я искал много времени, никаких ключей к разгадке.

Я знаю, как настроить NSAttributedString, тогда что мне делать, чтобы отображать текст на iPhone / iPad с форматированным текстом?

Официальные документы говорят, что его следует использовать CoreText.Framework, что это значит?

Есть ли такой простой способ?

NSAttributedString *str;
.....
UILabel *label;
label.attributedString = str;

Однако приведенный выше ответ верен. Кодируйте подобный код и убедитесь, что вы добавили фреймворк CoreText в связанные фреймворки.
mxcl

Спасибо, я оставил правильный ответ Уэсу
Джеку

Three20 ooks - довольно впечатляющая библиотека: github.com/facebook/three20
David H

87
Три20 - это чушь.
bandejapaisa

4
Это раздражает, но не думаю, что это хуже. Последние 6 месяцев я поддерживал проект, который использует Three20 ... некоторые вещи, которые они делают с памятью, сбивают меня с толку. Код действительно хрупкий, поскольку он не обрабатывает память ортодоксальным образом. Гораздо лучше делать то, что они предоставляют, самому. Вряд ли вам понадобится все, что они предоставляют. Сделай сам ... ты узнаешь больше, это веселее, у тебя, наверное, получится лучше!
bandejapaisa

Ответы:


79

Вам следует взглянуть на OHAttributedLabel от AliSoftware . Это подкласс UILabel, который рисует NSAttributedString, а также предоставляет удобные методы для установки атрибутов NSAttributedString из классов UIKit.

Из образца, представленного в репо:

#import "NSAttributedString+Attributes.h"
#import "OHAttributedLabel.h"

/**(1)** Build the NSAttributedString *******/
NSMutableAttributedString* attrStr = [NSMutableAttributedString attributedStringWithString:@"Hello World!"];
// for those calls we don't specify a range so it affects the whole string
[attrStr setFont:[UIFont systemFontOfSize:12]];
[attrStr setTextColor:[UIColor grayColor]];
// now we only change the color of "Hello"
[attrStr setTextColor:[UIColor redColor] range:NSMakeRange(0,5)];


/**(2)** Affect the NSAttributedString to the OHAttributedLabel *******/
myAttributedLabel.attributedText = attrStr;
// Use the "Justified" alignment
myAttributedLabel.textAlignment = UITextAlignmentJustify;
// "Hello World!" will be displayed in the label, justified, "Hello" in red and " World!" in gray.

Примечание. В iOS 6+ вы можете отображать строки с атрибутами, используя свойство attributedText UILabel.


Не существует такой вещи, как UIAttributedLabel. Я думаю, вы имеете в виду OHAttributedLabel.
Erik B

5
В ноябре 2010 г. он был переименован в OHAttributedLabel . Я обновил свой ответ.
Уэс,

1
Спасибо, Вес! Вы и Оливье Халлигон, написавший код! Спасибо!
DenNukem

1
Спасибо @Wes за упоминание моего класса и спасибо @DenNukem за кредиты ... Я не знал, что он настолько известен;) В любом случае, я сделал много обновлений и исправлений для этого класса с момента первоначального сообщения, так что не не забудьте вытащить репозиторий github!
AliSoftware

Я получаю сообщение об ошибке в каждой строке вашего кода. Согласно документации, не предоставленные вами методы существуют в фактическом классе, я смущен: developer.apple.com/library/mac/#documentation/Cocoa/Reference/…
aryaxt

155

Начиная с iOS 6.0 это можно сделать так:

NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"Hello. That is a test attributed string."];
[str addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:NSMakeRange(3,5)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(10,7)];
[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue-Bold" size:20.0] range:NSMakeRange(20, 10)];
label.attributedText = str;

60
Первое правило программы разработчика iOS - не говорить о программе разработчика iOS.
Джереми Мойерс,

5
Второе правило программы iOS dev ... см. Первое правило.
futureelite7

32
Заявление о том, что кто-то нарушил NDA, означает подтверждение того, что представленный материал действительно относится к iOS6 и, следовательно, сам по себе является нарушением NDA. Вы должны написать что-то вроде «Невозможно комментировать то, что будет в [следующей версии], не нарушив NDA».
Hatfinch

Также, если вы обнаружите, что пишете много строк с атрибутами, посмотрите этот пост / категорию. Облегчает создание. raizlabs.com/dev/2014/03/nsattributedstring-creation-helpers
Alex Rouse,

15

Вам следует попробовать TTTAttributedLabel . Это прямая замена для UILabel, которая работает с NSAttributedString и достаточно производительна для UITableViewCells.


Этот класс находится в упомянутой ниже библиотеке Three20.
David H

10
Нет, это не из three20 (обратите внимание на 3 Ts)
vikingosegundo

6

Есть ли простые способы вроде

NSAttributedString * str;

UILabel * label;

label.attributedString = str;

Почти. Просто используйте CATextLayer. У него есть stringсвойство, которое можно установить на NSAttributedString.

РЕДАКТИРОВАТЬ (ноябрь 2012 г.): Конечно, все это изменилось в iOS 6. В iOS 6 вы можете делать именно то, что просил OP - назначать атрибутивную строку непосредственно метке attributedText.


1
Не могли бы вы быть более конкретными, например, привести пример использования?
Уильям Ню,

1
Да, это моя книга, Программирование iOS 5. Вот пример кода из книги: github.com/mattneub/Programming-iOS-Book-Examples/blob/master/…
Мэтт

6

Ответ на выравнивание текста с атрибутами UILabel в iOS 6: используйте NSMutableAttributedString и добавьте NSMutableParagraphStyle к атрибуту. Что-то вроде этого:

NSString *str = @"Hello World!";
NSRange strRange = NSMakeRange(0, str.length);
NSMutableAttributedString *attributedStr = [[NSMutableAttributedString alloc] initWithString:str];

NSMutableParagraphStyle *paragrahStyle = [[NSMutableParagraphStyle alloc] init];
[paragrahStyle setAlignment:NSTextAlignmentCenter];
[attributedStr addAttribute:NSParagraphStyleAttributeName value:paragrahStyle range:strRange];

myUILabel.attributedText = attributedStr;

6

Я подумал, что было бы полезно привести пример синтаксического анализа (упрощенной) HTML-строки для создания NSAttributedString.

Он не полный - он обрабатывает только теги <b> и <i> для начала и не беспокоится об обработке ошибок - но, надеюсь, также является полезным примером того, как начать работу с NSXMLParserDelegate ...


@interface ExampleHTMLStringToAttributedString : NSObject<NSXMLParserDelegate>

+(NSAttributedString*) getAttributedStringForHTMLText:(NSString*)htmlText WithFontSize:(CGFloat)fontSize;

@end

@interface ExampleHTMLStringToAttributedString()
@property NSString *mpString;
@property NSMutableAttributedString *mpAttributedString;

@property CGFloat mfFontSize;
@property NSMutableString *appendThisString;
@property BOOL mbIsBold;
@property BOOL mbIsItalic;
@end

@implementation ExampleHTMLStringToAttributedString
@synthesize mpString;
@synthesize mfFontSize;
@synthesize mpAttributedString;
@synthesize appendThisString;
@synthesize mbIsBold;
@synthesize mbIsItalic;

+(NSAttributedString*) getAttributedStringForHTMLText:(NSString*)htmlText WithFontSize:(CGFloat)fontSize {

    ExampleHTMLStringToAttributedString *me = [[ExampleHTMLStringToAttributedString alloc] initWithString:htmlText];
    return [me getAttributedStringWithFontSize:fontSize];
}

- (id)initWithString:(NSString*)inString {
    self = [super init];
    if (self) {
        if ([inString hasPrefix:@""]) {
          mpString = inString;
        } else {
            mpString = [NSString stringWithFormat:@"%@", inString];
        }
        mpAttributedString = [NSMutableAttributedString new];
    }
    return self;
}

-(NSAttributedString*) getAttributedStringWithFontSize:(CGFloat)fontSize {

    mfFontSize = fontSize;

    // Parse the XML
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:[mpString dataUsingEncoding:NSUTF8StringEncoding]];
    parser.delegate = self;
    if (![parser parse]) {
        return nil;
    }

    return mpAttributedString;
}

-(void) appendTheAccumulatedText {
    UIFont *theFont = nil;

    if (mbIsBold && mbIsItalic) {
        // http://stackoverflow.com/questions/1384181/italic-bold-and-underlined-font-on-iphone
        theFont = [UIFont fontWithName:@"Helvetica-BoldOblique" size:mfFontSize];
    } else if (mbIsBold) {
       theFont = [UIFont boldSystemFontOfSize:mfFontSize];
    } else if (mbIsItalic) {
        theFont = [UIFont italicSystemFontOfSize:mfFontSize];
    } else {
        theFont = [UIFont systemFontOfSize:mfFontSize];
    }

    NSAttributedString *appendThisAttributedString =
    [[NSAttributedString alloc]
     initWithString:appendThisString
     attributes:@{NSFontAttributeName : theFont}];

    [mpAttributedString appendAttributedString:appendThisAttributedString];

    [appendThisString setString:@""];
}

#pragma NSXMLParserDelegate delegate

-(void)parserDidStartDocument:(NSXMLParser *)parser{
    appendThisString = [NSMutableString new];
    mbIsBold = NO;
    mbIsItalic = NO;
}

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    if ([elementName isEqualToString:@"body"]){
    } else if ([elementName isEqualToString:@"i"]) {
      [self appendTheAccumulatedText];
        mbIsItalic = YES;
    } else if ([elementName isEqualToString:@"b"]) {
      [self appendTheAccumulatedText];
        mbIsBold = YES;
    }
}

-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    if ([elementName isEqualToString:@"body"]){
      [self appendTheAccumulatedText];
    } else if ([elementName isEqualToString:@"i"]) {
      [self appendTheAccumulatedText];
      mbIsItalic = NO;
    } else if ([elementName isEqualToString:@"b"]) {
        [self appendTheAccumulatedText];
        mbIsBold = NO;
    }
}

-(void)parserDidEndDocument:(NSXMLParser *)parser{
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    [appendThisString appendString:string];
}

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
}

@end


Чтобы использовать, сделайте что-то вроде этого:


  self.myTextView.attributedText = [ExampleHTMLStringToAttributedString getAttributedStringForHTMLText:@"this is <b>bold</b> text" WithFontSize:self.myTextView.pointSize];


5

Начиная с iOS 6.0 это можно сделать так: еще один пример кода.

NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"This is my test code to test this label style is working or not on the text to show other user"];

[str addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,31)];
[str addAttribute:NSBackgroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(61,10)];

[str addAttribute:NSFontAttributeName value: [UIFont fontWithName:@"Helvetica-Bold" size:13.0] range:NSMakeRange(32, 28)];
[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica-Bold" size:13.0] range:NSMakeRange(65, 20)];

_textLabel.attributedText = str;

2

Для Swift используйте это,

Тексты заголовков станут жирными,

var title = NSMutableAttributedString(string: "Title Text")

    title.addAttributes([NSFontAttributeName: UIFont(name: "AvenirNext-Bold", size: iCurrentFontSize)!], range: NSMakeRange(0, 4))

    label.attributedText = title

2

Я знаю, что немного поздно, Но другим будет полезно,

NSMutableAttributedString* attrStr = [[NSMutableAttributedString alloc] initWithString:@"string" attributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}];

[self.label setAttributedText:newString];

Добавьте желаемый атрибут в словарь и передайте его как параметр атрибутов

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.