Texto en negrita y negrita en una sola UILabel?

¿Cómo sería posible incluir texto en negrita y negrita en uiLabel?

Prefiero no usar un UIWebView. También he leído que esto puede ser posible usando NSAttributedString, pero no tengo idea de cómo usarlo. ¿Algunas ideas?

Apple logra esto en varias de sus aplicaciones; Ejemplos Captura de pantalla: Texto del enlace

¡Gracias! – Dom

Actualización para Swift3

En Swift no tenemos que lidiar con iOS5, además de que la syntax es más corta, por lo que todo se vuelve realmente simple:

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() 

Bono: Internacionalización

Algunas personas comentaron sobre la internacionalización. Personalmente, creo que esto está fuera del scope de esta pregunta, pero para fines educativos, así es como lo haría

 // 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 (suponiendo que Localizable.strings en inglés y japonés estén disponibles)

enter image description here

enter image description here


Respuesta anterior para iOS6 y posterior (Objective-C todavía funciona):

En iOS6 UILabel , UIButton , UITextView , UITextField , admite cadenas atribuidas, lo que significa que no es necesario crear CATextLayer como destinatario de cadenas atribuidas. Además, para hacer la cadena atribuida ya no necesitamos jugar con CoreText 🙂 Tenemos nuevas clases en obj-c Foundation.framework como NSParagraphStyle y otras constantes que nos harán la vida más fácil. ¡Hurra!

Entonces, si tenemos esta cadena:

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

Solo necesitamos crear la cadena atribuida:

 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]; } 

Hay un par de buenas entradas de blog aquí de chicos de invasivecode que explican con más ejemplos los usos de NSAttributedString , busque “Introducción a NSAttributedString para iOS 6” y “Cadenas atribuidas para iOS usando Interface Builder” 🙂

PD: el código anterior debería funcionar pero fue comstackdo por el cerebro. Espero que sea suficiente 🙂


Vieja respuesta para iOS5 y abajo

¡Use CATextLayer con NSAttributedString! mucho más ligero y más simple que 2 UILabels. (iOS 3.2 y superior)

Ejemplo.

No olvide agregar QuartzCore framework (necesario para CALayers) y CoreText (necesario para la cadena atribuida).

 #import  #import  

El ejemplo siguiente agregará una subcapa a la barra de herramientas del controlador de navegación. à la Mail.app en el 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; } } 

En este ejemplo, solo tengo dos tipos diferentes de letra (negrita y normal) pero también podría tener diferentes tamaños de fuente, diferentes colores, cursiva, subrayado, etc. Eche un vistazo a las claves de cadena de atributos NSAttributedString / NSMutableAttributedString y CoreText .

Espero eso ayude

Pruebe una categoría en UILabel:

Así es como se usa:

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

Y aquí está la categoría

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]; } 

Tenga en cuenta que esto solo funcionará en iOS 6 y versiones posteriores. Simplemente será ignorado en iOS 5 y anteriores.

Hay una categoría basada en la categoría de bbrame. Funciona de manera similar, pero le permite audazmente el mismo UILabel varias veces con resultados acumulativos.

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 

Con estas correcciones, puede usarlo varias veces, por ejemplo:

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

resultará con: ” Actualizado: 2012/10/14 21:59 PM “.

Eso es fácil de hacer en Interface Builder :

1) hacer UILabel atribuido en el inspector de atributos

Ejemplo valiente Paso 1

2) selecciona la parte de la frase que quieras hacer en negrita

Negrita, ejemplo, paso 2

3) cambie su fuente (o negrita de la misma fuente) en el selector de fuente

Ejemplo en negrita Paso 3

¡Eso es todo!

Funcionó para mí:

 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 la versión Swift: mira aquí

He adoptado la respuesta de Crazy Yoghurt para las extensiones de 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.. 

Puede que no haya una buena conversión entre Range y NSRange, pero no encontré algo mejor.

Echa un vistazo a TTTAttributedLabel . Es un reemplazo directo para UILabel que le permite tener fonts y colores mezclados en una sola etiqueta estableciendo un NSAttributedString como el texto para esa etiqueta.

En este caso, podrías intentarlo

 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 hacer que el texto sea negrita y subrayado en UILabel. Solo agrega las siguientes líneas en tu 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; 

Usa el siguiente código Espero que te ayude

 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 satisfaga tu necesidad. Suministre la cadena para procesarla como entrada y suministre las palabras que deben ser negritas / coloreadas como entrada.

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

Gracias. Feliz Codificación.

No es necesario NSRange con el siguiente código que acabo de implementar en mi proyecto (en 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)") 

Si desea facilitar el uso de cadenas atribuidas, intente utilizar Attributed String Creator, que generará el código para usted. https://itunes.apple.com/us/app/attributed-string-creator/id730928349