trucos para negrita letras letra escribir cursiva como colores azules iphone objective-c ipad nsattributedstring

iphone - para - ¿Texto en negrita y no en negrita en una sola UILabel?



negrita en html css (14)

¿Cómo sería posible incluir texto en negrita y no en negrita en una 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; Captura de pantalla de ejemplos:

¡Gracias! - Dom


Actualización para Swift3

En Swift no tenemos que lidiar con cosas viejas de iOS5, además de que la sintaxis es más corta, por lo que todo se vuelve muy 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()

Bonus: Internacionalización

Algunas personas comentaron sobre la internacionalización. Personalmente, creo que esto está fuera del alcance de esta pregunta, pero para fines de instrucción, 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<Int> 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 las cadenas localizable en inglés y japonés están disponibles)

Respuesta anterior para iOS6 y versiones posteriores (Objective-C aún funciona):

En iOS6 UILabel , UIButton , UITextView , UITextField , admiten cadenas atribuidas, lo que significa que no necesitamos crear CATextLayer s como nuestro destinatario para las 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 harán nuestra 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 publicaciones introductorias aquí de chicos en invasivecode que explican con más ejemplos de usos de NSAttributedString , busque "Introduction to NSAttributedString for iOS 6" y " Atributed strings for iOS usando Interface Builder" :)

PD: sobre el código debería funcionar pero fue compilado de forma cerebral. Espero que sea suficiente :)

Respuesta antigua para iOS5 y versiones anteriores

Utilice un CATextLayer con una NSAttributedString! Mucho más ligero y sencillo que 2 UILabels. (iOS 3.2 y superior)

Ejemplo.

No te olvides de agregar el marco de QuartzCore (necesario para CALayers) y CoreText (necesario para la cadena atribuida).

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

El siguiente ejemplo 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 fuente (negrita y normal), pero también puede tener un tamaño de fuente diferente, color diferente, cursiva, subrayado, etc. Mire las claves de cadena de atributos NSAttributedString / NSMutableAttributedString y CoreText .

Espero eso ayude


Echa un vistazo a TTTAttributedLabel . Es un reemplazo directo para UILabel que le permite combinar fuentes y colores en una sola etiqueta al establecer una 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, e.g. 2012/10/14*/]; [notifyingStr endEditing]; displayLabel.attributedText = notifyingStr; // or [displayLabel setAttributedText: notifyingStr];


Eso es fácil de hacer en Interface Builder :

1) hacer UILabel Atribuido en inspector de atributos

2) Seleccione la parte de la frase que desea poner en negrita

3) cambiar su fuente (o el tipo de letra en negrita de la misma fuente) en el selector de fuente

¡Eso es todo!


Espero que esta cumpla con su necesidad. Suministre la cadena para procesar como entrada y proporcione las palabras que deben estar en negrita / 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..<parentString.endIndex, options: .byWords) { (substring, substringRange, _, _) in if substring == eachWord { parentAttributedString.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: 15), range: NSRange(substringRange, in: parentString)) parentAttributedString.addAttribute(.foregroundColor, value: color, range: NSRange(substringRange, in: parentString)) } } } } return parentAttributedString }

Gracias. Feliz codificacion


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: ver Here


Hay una categoría basada en la categoría de bbrame. Funciona de manera similar, pero le permite poner en negrita la misma 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 puedes 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 ".


He adoptado la respuesta de Crazy Yoghurt a las extensiones de swift.

extension UILabel { func boldRange(_ range: Range<String.Index>) { 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..<text.string.endIndex, locale: nil) } if let r = range { boldRange(r) } } } }

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


No necesito 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


Para poner el texto en negrita y subrayado en una UILabel. Simplemente agregue las siguientes líneas en su 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;


Prueba 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 versiones anteriores.



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


Utilice el siguiente código. Espero que te sirva de ayuda.

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