¿Cambiar el color de la cadena con NSAttributedString?

147

Tengo un control deslizante para una encuesta que muestra las siguientes cadenas en función del valor del control deslizante: "Muy malo, malo, bueno, bueno, muy bueno".

Aquí está el código para el control deslizante:

- (IBAction) sliderValueChanged:(UISlider *)sender {
    scanLabel.text = [NSString stringWithFormat:@" %.f", [sender value]];
    NSArray *texts=[NSArray arrayWithObjects:@"Very Bad", @"Bad", @"Okay", @"Good", @"Very Good", @"Very Good", nil];
    NSInteger sliderValue=[sender value]; //make the slider value in given range integer one.
    self.scanLabel.text=[texts objectAtIndex:sliderValue];
}

Quiero que "Muy malo" sea rojo, "Malo" sea naranja, "Bien" sea amarillo, "Bueno" y "Muy bueno" sea verde.

No entiendo cómo usar NSAttributedStringpara hacer esto.

Adán
fuente
¿Te refieres a un UISlider? Eso no tiene una etiqueta. Entonces, ¿se trata básicamente de un UILabel con un color de fuente? ¿O quieres una parte del texto coloreada?
Roger
2
posible duplicado de ¿Cómo se usa NSAttributedString?
John Parker el
Use esta biblioteca, es bastante simple. github.com/iOSTechHub/AttributedString
Ashish Chauhan

Respuestas:

196

No hay necesidad de usar NSAttributedString. Todo lo que necesitas es una etiqueta simple con el correcto textColor. Además, esta solución simple funcionará con todas las versiones de iOS, no solo con iOS 6.

Pero si necesita utilizarlo innecesariamente NSAttributedString, puede hacer algo como esto:

UIColor *color = [UIColor redColor]; // select needed color
NSString *string = ... // the string to colorize
NSDictionary *attrs = @{ NSForegroundColorAttributeName : color };
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:string attributes:attrs];
self.scanLabel.attributedText = attrStr;
rmaddy
fuente
44
No entiendo todos los votos negativos. Mi respuesta es mucho más simple que usar una cadena atribuida. El OP no tiene necesidad de usarlo NSAttributedStringpara esta tarea. Sería una cosa si el texto de la etiqueta necesitara múltiples atributos pero no los necesita. Toda la etiqueta debe ser de un color a la vez.
rmaddy
@ RubénE.Marín Pero ese es el problema. El OP pensó erróneamente que la solución requería el uso NSAttributedString. Entonces eso es lo que pidieron. La verdadera pregunta debería haber sido "Cómo configurar el color de la etiqueta en función de su valor" . Señalé que la solución no requiere NSAttributedStringy mostré una respuesta mucho más simple. Y el OP aceptó al aceptar mi respuesta mucho más simple. Si el OP realmente quisiera NSAttributedString, no habrían aceptado mi respuesta. Entonces no hay razón para los votos negativos. Respondí la verdadera pregunta y el OP aceptó.
rmaddy
24
En ese caso, habría resuelto la pregunta con NSAttributedString y, después de eso, habría señalado su solución más simple y más eficiente para el caso particular del OP. Las personas que llegan a esta pregunta pueden sentirse frustradas por su solución porque están buscando formas de cambiar el color del texto en NSAttributedString (y eso explicaría sus votos negativos).
Ruben Marin
15
Rubén tiene razón: vine aquí porque necesito establecer el color en una cadena atribuida, porque estoy construyendo una cadena atribuida compuesta con múltiples colores y tamaños de fuente. Y la información clave que necesitaba era la NSForegroundColorAttributeNameclave, que tuve dificultades para encontrar en los documentos de Apple.
Erik van der Neut
55
¡Gracias por responder la pregunta! incluso si OP no lo necesitaba realmente. Muchas veces busco algo en Google, termino en una pregunta de desbordamiento de pila que es exactamente lo que estoy buscando, solo para descubrir que el sabio que respondió la pregunta decidió que el OP no necesitaba realmente lo que el título de la pregunta estaba pidiendo y respondió una pregunta completamente diferente. Bueno, las personas en el futuro que provengan de los resultados de búsqueda, de los cuales podría haber 1000 en lugar del OP 1, en realidad podrían querer una solución a la pregunta formulada en el título de la publicación. </rant>
danny
112

Use algo como esto (no está compilado)

NSMutableAttributedString *string = [[NSMutableAttributedString alloc]initWithString:self.text.text];
NSRange range=[self.myLabel.text rangeOfString:texts[sliderValue]]; //myLabel is the outlet from where you will get the text, it can be same or different

NSArray *colors=@[[UIColor redColor],
                  [UIColor redColor],
                  [UIColor yellowColor],
                  [UIColor greenColor]
                 ];

[string addAttribute:NSForegroundColorAttributeName 
               value:colors[sliderValue] 
               range:range];           

[self.scanLabel setAttributedText:texts[sliderValue]];
Anoop Vaidya
fuente
¡Hola Anoop, me alegro de verte de nuevo! Seguí el código que proporcionó, reemplacé self.text.text con self.scanLabel.text, pero recibo un error en "word". Intenté reemplazarlo con @ "Very Bad" sin suerte.
Adam
Copié mi respuesta desde aquí stackoverflow.com/questions/14231879/…
Anoop Vaidya
Gracias Anoop, pero no tuve suerte. - [__ NSCFString _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes:]: selector no reconocido enviado a la instancia 0x1f845af0 2013-01-11 16: 27: 34.939 yellaProto [7829: 907] *** Aplicación de finalización debido a una excepción no detectada 'NSInvalidA_: Argumento: NSC, NS:' motivo: NSExvalidAr. _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes:]: selector no reconocido enviado a la instancia 0x1f845af0 '
Adam
Solo trato de averiguar qué "textos"
Morkrom
@Morkrom: si ves el segundo comentario en esta respuesta, entonces sabrás: p
Anoop Vaidya
48

En Swift 4 :

// Custom color
let greenColor = UIColor(red: 10/255, green: 190/255, blue: 50/255, alpha: 1)
// create the attributed colour
let attributedStringColor = [NSAttributedStringKey.foregroundColor : greenColor];
// create the attributed string
let attributedString = NSAttributedString(string: "Hello World!", attributes: attributedStringColor)
// Set the label
label.attributedText = attributedString

En Swift 3 :

// Custom color
let greenColor = UIColor(red: 10/255, green: 190/255, blue: 50/255, alpha: 1)
// create the attributed color
let attributedStringColor : NSDictionary = [NSForegroundColorAttributeName : greenColor];
// create the attributed string
let attributedString = NSAttributedString(string: "Hello World!", attributes: attributedStringColor as? [String : AnyObject])
// Set the label
label.attributedText = attributedString 

Disfrutar.

App Dev Guy
fuente
28

Para Swift 5:

var attributes = [NSAttributedString.Key: AnyObject]()
attributes[.foregroundColor] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString

Para Swift 4:

var attributes = [NSAttributedStringKey: AnyObject]()
attributes[.foregroundColor] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString

Para Swift 3:

var attributes = [String: AnyObject]()
attributes[NSForegroundColorAttributeName] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString
pableiros
fuente
7

Puedes crear NSAttributedString

NSDictionary *attributes = @{ NSForegroundColorAttributeName : [UIColor redColor] };
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"My Color String" attributes:attrs];

O NSMutableAttributedStringpara aplicar atributos personalizados con rangos.

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@%@", methodPrefix, method] attributes: @{ NSFontAttributeName : FONT_MYRIADPRO(48) }];
[attributedString addAttribute:NSFontAttributeName value:FONT_MYRIADPRO_SEMIBOLD(48) range:NSMakeRange(methodPrefix.length, method.length)];

Atributos disponibles: NSAttributedStringKey


ACTUALIZAR:

Swift 5.1

let message: String = greeting + someMessage
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 2.0
    
// Note: UIFont(appFontFamily:ofSize:) is extended init.
let regularAttributes: [NSAttributedString.Key : Any] = [.font : UIFont(appFontFamily: .regular, ofSize: 15)!, .paragraphStyle : paragraphStyle]
let boldAttributes = [NSAttributedString.Key.font : UIFont(appFontFamily: .semiBold, ofSize: 15)!]

let mutableString = NSMutableAttributedString(string: message, attributes: regularAttributes)
mutableString.addAttributes(boldAttributes, range: NSMakeRange(0, greeting.count))
Lal Krishna
fuente
5

Con Swift 4, NSAttributedStringKeytiene una propiedad estática llamada foregroundColor. foregroundColortiene la siguiente declaración:

static let foregroundColor: NSAttributedStringKey

El valor de este atributo es un UIColorobjeto. Use este atributo para especificar el color del texto durante la representación. Si no especifica este atributo, el texto se representa en negro.

El siguiente código de Playground muestra cómo configurar el color del texto de una NSAttributedStringinstancia con foregroundColor:

import UIKit

let string = "Some text"
let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
let attributedString = NSAttributedString(string: string, attributes: attributes)

El código siguiente muestra una posible UIViewControlleraplicación que se basa en NSAttributedStringel objeto de actualizar el color del texto y el texto de una UILabelde una UISlider:

import UIKit

enum Status: Int {
    case veryBad = 0, bad, okay, good, veryGood

    var display: (text: String, color: UIColor) {
        switch self {
        case .veryBad:  return ("Very bad", .red)
        case .bad:      return ("Bad", .orange)
        case .okay:     return ("Okay", .yellow)
        case .good:     return ("Good", .green)
        case .veryGood: return ("Very good", .blue)
        }
    }

    static let minimumValue = Status.veryBad.rawValue
    static let maximumValue = Status.veryGood.rawValue
}
final class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var slider: UISlider!
    var currentStatus: Status = Status.veryBad {
        didSet {
            // currentStatus is our model. Observe its changes to update our display
            updateDisplay()
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Prepare slider
        slider.minimumValue = Float(Status.minimumValue)
        slider.maximumValue = Float(Status.maximumValue)

        // Set display
        updateDisplay()
    }

    func updateDisplay() {
        let attributes = [NSAttributedStringKey.foregroundColor : currentStatus.display.color]
        let attributedString = NSAttributedString(string: currentStatus.display.text, attributes: attributes)
        label.attributedText = attributedString
        slider.value = Float(currentStatus.rawValue)
    }

    @IBAction func updateCurrentStatus(_ sender: UISlider) {
        let value = Int(sender.value.rounded())
        guard let status = Status(rawValue: value) else { fatalError("Could not get Status object from value") }
        currentStatus = status
    }

}

Sin embargo, tenga en cuenta que realmente no necesita usarlo NSAttributedStringpara tal ejemplo y simplemente puede confiar en UILabel's texty textColorpropiedades. Por lo tanto, puede reemplazar su updateDisplay()implementación con el siguiente código:

func updateDisplay() {
    label.text = currentStatus.display.text
    label.textColor = currentStatus.display.color
    slider.value = Float(currentStatus.rawValue)
}
Imanou Petit
fuente
2

Actualización para Swift 4.2

var attributes = [NSAttributedString.Key: AnyObject]()

attributes[.foregroundColor] = UIColor.blue

let attributedString = NSAttributedString(string: "Very Bad",
attributes: attributes)

label.attributedText = attributedString
Mithra Singam
fuente
1

Un forro para Swift:

NSAttributedString(string: "Red Text", attributes: [.foregroundColor: UIColor.red])
Fedotchenco Denis
fuente