Bold e Non-Bold texto em um único UILabel?

Como seria possível include texto em negrito e não em negrito em um uiLabel?

Eu prefiro não usar um UIWebView .. Eu também li isso pode ser possível usando NSAttributedString mas não tenho idéia de como usar isso. Alguma ideia?

A Apple consegue isso em vários de seus aplicativos; Exemplos de captura de canvas: Texto do link

Obrigado! – Dom

Atualização para o Swift3

No Swift, não temos que lidar com coisas antigas do iOS5, além da syntax ser mais curta, então tudo se torna realmente simples:

func attributedString(from string: String, nonBoldRange: NSRange?) -> NSAttributedString { let fontSize = UIFont.systemFontSize let attrs = [ NSFontAttributeName: UIFont.boldSystemFont(ofSize: fontSize), NSForegroundColorAttributeName: UIColor.black ] let nonBoldAttribute = [ NSFontAttributeName: UIFont.systemFont(ofSize: fontSize), ] let attrStr = NSMutableAttributedString(string: string, attributes: attrs) if let range = nonBoldRange { attrStr.setAttributes(nonBoldAttribute, range: range) } return attrStr } 

Uso:

 let targetString = "Updated 2012/10/14 21:59 PM" let range = NSMakeRange(7, 12) let label = UILabel(frame: CGRect(x:0, y:0, width:350, height:44)) label.backgroundColor = UIColor.white label.attributedText = attributedString(from: targetString, nonBoldRange: range) label.sizeToFit() 

Bônus: Internacionalização

Algumas pessoas comentaram sobre internacionalização. Eu pessoalmente acho que isso está fora do escopo desta questão, mas para fins de instrução é assim que eu faria

 // Date we want to show let date = Date() // Create the string. // I don't set the locale because the default locale of the formatter is `NSLocale.current` so it's good for internationalisation :p let formatter = DateFormatter() formatter.dateStyle = .medium formatter.timeStyle = .short let targetString = String(format: NSLocalizedString("Update %@", comment: "Updated string format"), formatter.string(from: date)) // Find the range of the non-bold part formatter.timeStyle = .none let nonBoldRange = targetString.range(of: formatter.string(from: date)) // Convert Range into NSRange let nonBoldNSRange: NSRange? = nonBoldRange == nil ? nil : NSMakeRange(targetString.distance(from: targetString.startIndex, to: nonBoldRange!.lowerBound), targetString.distance(from: nonBoldRange!.lowerBound, to: nonBoldRange!.upperBound)) // Now just build the attributed string as before :) label.attributedText = attributedString(from: targetString, nonBoldRange: nonBoldNSRange) 

Resultado (Supondo Inglês e Japonês Localizable.strings estão disponíveis)

insira a descrição da imagem aqui

insira a descrição da imagem aqui


Resposta anterior para iOS6 e posterior (Objective-C ainda funciona):

No iOS6, UILabel , UIButton , UITextView , UITextField , suportam strings atribuídas, o que significa que não precisamos criar CATextLayer s como nosso destinatário para as strings atribuídas. Além disso, para fazer a string atribuída, não precisamos mais brincar com o CoreText 🙂 Temos novas classs no obj-c Foundation.framework como o NSParagraphStyle e outras constantes que facilitarão a nossa vida. Yay!

Então, se tivermos essa string:

 NSString *text = @"Updated: 2012/10/14 21:59" 

Nós só precisamos criar a string atribuída:

 if ([_label respondsToSelector:@selector(setAttributedText:)]) { // iOS6 and above : Use NSAttributedStrings // Create the attributes const CGFloat fontSize = 13; NSDictionary *attrs = @{ NSFontAttributeName:[UIFont boldSystemFontOfSize:fontSize], NSForegroundColorAttributeName:[UIColor whiteColor] }; NSDictionary *subAttrs = @{ NSFontAttributeName:[UIFont systemFontOfSize:fontSize] }; // Range of " 2012/10/14 " is (8,12). Ideally it shouldn't be hardcoded // This example is about attributed strings in one label // not about internationalisation, so we keep it simple :) // For internationalisation example see above code in swift const NSRange range = NSMakeRange(8,12); // Create the attributed string (text + attributes) NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:text attributes:attrs]; [attributedText setAttributes:subAttrs range:range]; // Set it in our UILabel and we are done! [_label setAttributedText:attributedText]; } else { // iOS5 and below // Here we have some options too. The first one is to do something // less fancy and show it just as plain text without attributes. // The second is to use CoreText and get similar results with a bit // more of code. Interested people please look down the old answer. // Now I am just being lazy so :p [_label setText:text]; } 

Há um bom número de posts introdutórios aqui de caras em invasivecode que explicam com mais exemplos de usos de NSAttributedString , procure por “Introdução ao NSAttributedString para iOS 6” e “Strings atribuídas para iOS usando o Interface Builder” 🙂

PS: Acima do código, deve funcionar, mas foi compilado pelo cérebro. Eu espero que seja o suficiente 🙂


Resposta antiga para iOS5 e abaixo

Use um CATextLayer com um NSAttributedString! muito mais leve e simples que 2 UILabels. (iOS 3.2 e acima)

Exemplo.

Não esqueça de adicionar o framework QuartzCore (necessário para as CALayers) e o CoreText (necessário para a string atribuída).

 #import  #import  

Abaixo, o exemplo adicionará uma subcamada à barra de ferramentas do controlador de navegação. à la Mail.app no ​​iPhone. 🙂

 - (void)setRefreshDate:(NSDate *)aDate { [aDate retain]; [refreshDate release]; refreshDate = aDate; if (refreshDate) { /* Create the text for the text layer*/ NSDateFormatter *df = [[NSDateFormatter alloc] init]; [df setDateFormat:@"MM/dd/yyyy hh:mm"]; NSString *dateString = [df stringFromDate:refreshDate]; NSString *prefix = NSLocalizedString(@"Updated", nil); NSString *text = [NSString stringWithFormat:@"%@: %@",prefix, dateString]; [df release]; /* Create the text layer on demand */ if (!_textLayer) { _textLayer = [[CATextLayer alloc] init]; //_textLayer.font = [UIFont boldSystemFontOfSize:13].fontName; // not needed since `string` property will be an NSAttributedString _textLayer.backgroundColor = [UIColor clearColor].CGColor; _textLayer.wrapped = NO; CALayer *layer = self.navigationController.toolbar.layer; //self is a view controller contained by a navigation controller _textLayer.frame = CGRectMake((layer.bounds.size.width-180)/2 + 10, (layer.bounds.size.height-30)/2 + 10, 180, 30); _textLayer.contentsScale = [[UIScreen mainScreen] scale]; // looks nice in retina displays too :) _textLayer.alignmentMode = kCAAlignmentCenter; [layer addSublayer:_textLayer]; } /* Create the attributes (for the attributed string) */ CGFloat fontSize = 13; UIFont *boldFont = [UIFont boldSystemFontOfSize:fontSize]; CTFontRef ctBoldFont = CTFontCreateWithName((CFStringRef)boldFont.fontName, boldFont.pointSize, NULL); UIFont *font = [UIFont systemFontOfSize:13]; CTFontRef ctFont = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize, NULL); CGColorRef cgColor = [UIColor whiteColor].CGColor; NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: (id)ctBoldFont, (id)kCTFontAttributeName, cgColor, (id)kCTForegroundColorAttributeName, nil]; CFRelease(ctBoldFont); NSDictionary *subAttributes = [NSDictionary dictionaryWithObjectsAndKeys:(id)ctFont, (id)kCTFontAttributeName, nil]; CFRelease(ctFont); /* Create the attributed string (text + attributes) */ NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:text attributes:attributes]; [attrStr addAttributes:subAttributes range:NSMakeRange(prefix.length, 12)]; //12 is the length of " MM/dd/yyyy/ " /* Set the attributes string in the text layer :) */ _textLayer.string = attrStr; [attrStr release]; _textLayer.opacity = 1.0; } else { _textLayer.opacity = 0.0; _textLayer.string = nil; } } 

Neste exemplo eu só tenho dois tipos diferentes de fonte (negrito e normal), mas você também pode ter tamanho de fonte diferente, cor diferente, itálico, sublinhado, etc. Dê uma olhada nas chaves de string de atributos NSAttributedString / NSMutableAttributedString e CoreText .

Espero que ajude

Experimente uma categoria no UILabel:

Veja como é usado:

 myLabel.text = @"Updated: 2012/10/14 21:59 PM"; [myLabel boldSubstring: @"Updated:"]; [myLabel boldSubstring: @"21:59 PM"]; 

E aqui está a categoria

UILabel + Boldify.h

 - (void) boldSubstring: (NSString*) substring; - (void) boldRange: (NSRange) range; 

UILabel + Boldify.m

 - (void) boldRange: (NSRange) range { if (![self respondsToSelector:@selector(setAttributedText:)]) { return; } NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText]; [attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range]; self.attributedText = attributedText; } - (void) boldSubstring: (NSString*) substring { NSRange range = [self.text rangeOfString:substring]; [self boldRange:range]; } 

Observe que isso funcionará somente no iOS 6 e posterior. Ele será simplesmente ignorado no iOS 5 e versões anteriores.

Há categoria baseada na categoria do bbrame. Ele funciona de maneira semelhante, mas permite que você corrija o mesmo UILabel várias vezes com resultados cumulativos.

UILabel + Boldify.h

 @interface UILabel (Boldify) - (void) boldSubstring: (NSString*) substring; - (void) boldRange: (NSRange) range; @end 

UILabel + Boldify.m

 @implementation UILabel (Boldify) - (void)boldRange:(NSRange)range { if (![self respondsToSelector:@selector(setAttributedText:)]) { return; } NSMutableAttributedString *attributedText; if (!self.attributedText) { attributedText = [[NSMutableAttributedString alloc] initWithString:self.text]; } else { attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText]; } [attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range]; self.attributedText = attributedText; } - (void)boldSubstring:(NSString*)substring { NSRange range = [self.text rangeOfString:substring]; [self boldRange:range]; } @end 

Com essas correções você pode usá-lo várias vezes, por exemplo:

 myLabel.text = @"Updated: 2012/10/14 21:59 PM"; [myLabel boldSubstring: @"Updated:"]; [myLabel boldSubstring: @"21:59 PM"]; 

resultará com: ” Atualizado: 2012/10/14 21:59 “.

Isso é fácil de fazer no Interface Builder :

1) faça o UILabel Atribuído no Inspetor de Atributos

Exemplo em negrito, passo 1

2) selecione parte da frase que você quer tornar em negrito

Exemplo em negrito, passo 2

3) mudar sua fonte (ou fonte negrito da mesma fonte) no seletor de fonte

Exemplo em negrito, passo 3

Isso é tudo!

Funcionou para mim:

 CGFloat boldTextFontSize = 17.0f; myLabel.text = [NSString stringWithFormat:@"%@ 2012/10/14 %@",@"Updated:",@"21:59 PM"]; NSRange range1 = [myLabel.text rangeOfString:@"Updated:"]; NSRange range2 = [myLabel.text rangeOfString:@"21:59 PM"]; NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:myLabel.text]; [attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:boldTextFontSize]} range:range1]; [attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:boldTextFontSize]} range:range2]; myLabel.attributedText = attributedText; 

Para a versão Swift: Veja aqui

Adotei a resposta do Crazy Yoghurt às extensões do Swift.

 extension UILabel { func boldRange(_ range: Range) { if let text = self.attributedText { let attr = NSMutableAttributedString(attributedString: text) let start = text.string.characters.distance(from: text.string.startIndex, to: range.lowerBound) let length = text.string.characters.distance(from: range.lowerBound, to: range.upperBound) attr.addAttributes([NSFontAttributeName: UIFont.boldSystemFont(ofSize: self.font.pointSize)], range: NSMakeRange(start, length)) self.attributedText = attr } } func boldSubstring(_ substr: String) { if let text = self.attributedText { var range = text.string.range(of: substr) let attr = NSMutableAttributedString(attributedString: text) while range != nil { let start = text.string.characters.distance(from: text.string.startIndex, to: range!.lowerBound) let length = text.string.characters.distance(from: range!.lowerBound, to: range!.upperBound) var nsRange = NSMakeRange(start, length) let font = attr.attribute(NSFontAttributeName, at: start, effectiveRange: &nsRange) as! UIFont if !font.fontDescriptor.symbolicTraits.contains(.traitBold) { break } range = text.string.range(of: substr, options: NSString.CompareOptions.literal, range: range!.upperBound.. 

Pode ser que não haja uma boa conversão entre Range e NSRange, mas não encontrei algo melhor.

Confira o TTTAtributedLabel . É um substituto imediato da UILabel que permite que você tenha fonts e colors misturadas em um único label definindo um NSAttributedString como o texto desse label.

Neste caso você poderia tentar,

 UILabel *displayLabel = [[UILabel alloc] initWithFrame:/*label frame*/]; displayLabel.font = [UIFont boldSystemFontOfSize:/*bold font size*/]; NSMutableAttributedString *notifyingStr = [[NSMutableAttributedString alloc] initWithString:@"Updated: 2012/10/14 21:59 PM"]; [notifyingStr beginEditing]; [notifyingStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:/*normal font size*/] range:NSMakeRange(8,10)/*range of normal string, eg 2012/10/14*/]; [notifyingStr endEditing]; displayLabel.attributedText = notifyingStr; // or [displayLabel setAttributedText: notifyingStr]; 

Para tornar o texto negrito e sublinhado em um UILabel. Basta adicionar as seguintes linhas no seu código.

 NSRange range1 = [lblTermsAndCondition.text rangeOfString:NSLocalizedString(@"bold_terms", @"")]; NSRange range2 = [lblTermsAndCondition.text rangeOfString:NSLocalizedString(@"bold_policy", @"")]; NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:lblTermsAndCondition.text]; [attributedText setAttributes:@{NSFontAttributeName:[UIFont fontWithName:fontBold size:12.0]} range:range1]; [attributedText setAttributes:@{NSFontAttributeName:[UIFont fontWithName:fontBold size:12.0]} range:range2]; [attributedText addAttribute:(NSString*)kCTUnderlineStyleAttributeName value:[NSNumber numberWithInt:kCTUnderlineStyleSingle] range:range1]; [attributedText addAttribute:(NSString*)kCTUnderlineStyleAttributeName value:[NSNumber numberWithInt:kCTUnderlineStyleSingle] range:range2]; lblTermsAndCondition.attributedText = attributedText; 

Use o código abaixo. Espero que ajude por você.

 NSString *needToChangeStr=@"BOOK"; NSString *display_string=[NSString stringWithFormat:@"This is %@",book]; NSMutableAttributedString *attri_str=[[NSMutableAttributedString alloc]initWithString:display_string]; int begin=[display_string length]-[needToChangeStr length]; int end=[needToChangeStr length]; [attri_str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue-Bold" size:30] range:NSMakeRange(begin, end)]; 

Espero que este atenda a sua necessidade. Forneça a string para processar como input e forneça as palavras que devem ser negrito / coloridas como input.

 func attributedString(parentString:String, arrayOfStringToProcess:[String], color:UIColor) -> NSAttributedString { let parentAttributedString = NSMutableAttributedString(string:parentString, attributes:nil) let parentStringWords = parentAttributedString.string.components(separatedBy: " ") if parentStringWords.count != 0 { let wordSearchArray = arrayOfStringToProcess.filter { inputArrayIndex in parentStringWords.contains(where: { $0 == inputArrayIndex } )} for eachWord in wordSearchArray { parentString.enumerateSubstrings(in: parentString.startIndex.. 

Obrigado. Codificação Feliz.

Não há necessidade de NSRange com o seguinte código que acabei de implementar no meu projeto (no Swift):

  //Code sets label (yourLabel)'s text to "Tap and hold(BOLD) button to start recording." let boldAttribute = [ //You can add as many attributes as you want here. NSFontAttributeName: UIFont(name: "HelveticaNeue-Bold", size: 18.0)!] let regularAttribute = [ NSFontAttributeName: UIFont(name: "HelveticaNeue-Light", size: 18.0)!] let beginningAttributedString = NSAttributedString(string: "Tap and ", attributes: regularAttribute ) let boldAttributedString = NSAttributedString(string: "hold ", attributes: boldAttribute) let endAttributedString = NSAttributedString(string: "button to start recording.", attributes: regularAttribute ) let fullString = NSMutableAttributedString() fullString.appendAttributedString(beginningAttributedString) fullString.appendAttributedString(boldAttributedString) fullString.appendAttributedString(endAttributedString) yourLabel.attributedText = fullString 

Swift 4:

 // attribute with color red and Bold var attrs1 = [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 20), NSAttributedStringKey.foregroundColor: UIColor.red] // attribute with color black and Non Bold var attrs2 = [NSAttributedStringKey.font: UIFont(name: "Roboto-Regular", size: 20), NSAttributedStringKey.foregroundColor: UIColor.black] var color1 = NSAttributedString(string: "RED", attributes: attrs1) var color2 = NSAttributedString(string: " BLACK", attributes: attrs2) var string = NSMutableAttributedString() string.append(color1) string.append(color2) // print the text with **RED** BLACK print("Final String : \(string)") 

Se você quiser facilitar o uso de strings atribuídas, tente usar o Attributed String Creator, que gerará o código para você. https://itunes.apple.com/us/app/attributed-string-creator/id730928349