iphone / ipad: exatamente como usar NSAttributedString?

102

Sim, muitas pessoas estão falando sobre Rich Text no iPhone / iPad e muitos sabem disso NSAttributedString.

Mas como usar NSAttributedString ? Procurei por muito tempo, sem extrair pistas para isso.

Eu sei como configurar um NSAttributedString , então o que devo fazer para exibir um texto no iPhone / iPad com rich text?

A documentação oficial diz que deve ser usado com CoreText.Framework , o que isso significa?

Existe alguma maneira simples como essa?

NSAttributedString *str;
.....
UILabel *label;
label.attributedString = str;
Jack
fonte
A resposta acima está correta. Codifique assim e certifique-se de adicionar a estrutura CoreText às suas estruturas vinculadas.
mxcl
Obrigado, deixei a resposta correta para Wes
Jack
Three20 ooks como uma biblioteca bem impressionante: github.com/facebook/three20
David H
87
Three20 é uma porcaria.
bandejapaisa
4
Isso é irritante, mas não acho que seja a pior coisa. Nos últimos 6 meses, tenho mantido um projeto que usa o Three20 ... algumas das coisas que eles fazem com a memória me confundem. O código é muito frágil, pois não trata a memória de uma forma ortodoxa. É muito melhor fazer o que eles fornecem a si mesmo. É improvável que você precise de tudo o que eles fornecem. Faça você mesmo ... você aprenderá mais, é mais divertido, provavelmente fará melhor!
bandejapaisa

Respostas:

79

Você deve dar uma olhada no OHAttributedLabel do AliSoftware . É uma subclasse de UILabel que desenha um NSAttributedString e também fornece métodos convenientes para definir os atributos de um NSAttributedString de classes UIKit.

Da amostra fornecida no repo:

#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.

Nota: No iOS 6+ você pode renderizar strings atribuídas usando a propriedade attributeText de UILabel.

Wes
fonte
Não existe UIAttributedLabel. Acho que você está se referindo a OHAttributedLabel.
Erik B
5
Ele foi renomeado OHAttributedLabel em um commit em novembro de 2010 . Eu atualizei minha resposta.
Wes
1
Obrigado Wes! Você e Olivier Halligon que escreveram o código! Obrigado!
DenNukem
1
Obrigado @Wes por mencionar minha aula, e obrigado @DenNukem pelos créditos ... Eu não sabia que era tão famoso;) De qualquer forma, eu fiz muitas atualizações e correções nesta aula desde o post original, então não não se esqueça de puxar o repositório github!
AliSoftware
Recebo um erro em cada linha do seu código. De acordo com a documentação que
nenhum
155

A partir do iOS 6.0, você pode fazer assim:

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;
RomanN
fonte
60
A primeira regra do programa de desenvolvimento do iOS é não falar sobre o programa de desenvolvimento do iOS.
Jeremy Moyers
5
A segunda regra do programa de desenvolvimento do iOS é ... veja a primeira regra.
futureelite7 de
32
Afirmar que alguém violou o NDA é confirmar que o material apresentado está realmente no iOS6 e, portanto, é uma violação do NDA. Você deve escrever algo como "Não é possível comentar sobre o que está na [próxima versão] sem quebrar o NDA".
hatfinch
Além disso, se você se pegar escrevendo muitas strings atribuídas, verifique este post / categoria. Torna a criação um pouco mais fácil. raizlabs.com/dev/2014/03/nsattributedstring-creation-helpers
Alex Rouse
15

Você deve tentar TTTAttributedLabel . É um substituto imediato para UILabel que funciona com NSAttributedString e tem desempenho suficiente para UITableViewCells.

Matt
fonte
Esta classe é encontrada na biblioteca Three20 mencionada abaixo.
David H
10
Não, isso não é de três20 (observe os 3 Ts)
vikingosegundo
6

Existe alguma maneira simples como

NSAttributedString * str;

Etiqueta UILabel *;

label.attributedString = str;

Quase. Basta usar um CATextLayer. Tem umstring propriedade que você pode definir como um NSAttributedString.

EDIT (novembro de 2012): É claro que tudo isso mudou no iOS 6. No iOS 6, você pode fazer exatamente o que o OP pediu - atribuir uma string atribuída diretamente a um rótulo attributedText.

mate
fonte
1
Você poderia ser mais específico, por exemplo, fornecer um exemplo de uso?
William Niu
1
Sim, é chamado de meu livro, Programação iOS 5. Aqui está o exemplo de código do livro: github.com/mattneub/Programming-iOS-Book-Examples/blob/master/…
matt
6

Resposta para o alinhamento de texto atribuído por UILabel no iOS 6: use NSMutableAttributedString e adicione NSMutableParagraphStyle ao atributo. Algo assim:

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;
elou
fonte
6

Achei que seria útil dar um exemplo de análise de uma string HTML (simplificada) para criar uma NSAttributedString.

Não está completo - ele apenas lida com tags <b> e <i>, para começar, e não se preocupa com nenhum tratamento de erros - mas, esperançosamente, também é um exemplo útil de como começar com 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


Para usar, faça algo assim:


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

Pete
fonte
5

A partir do iOS 6.0, você pode fazer assim: outro código de amostra.

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;
Ayaz
fonte
2

Para Swift use isso,

Isso fará com que TITL textos em negrito,

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

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

    label.attributedText = title
Mohammad Zaid Pathan
fonte
2

Eu sei que é um pouco tarde, mas será útil para outros,

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

[self.label setAttributedText:newString];

Adicione o atributo desejado ao dicionário e passe-o como um parâmetro de atributos

satheesh
fonte