UILabel con texto de dos colores diferentes

109

Quiero mostrar una cadena como esta en un UILabel:

Hay 5 resultados.

Donde el número 5 es de color rojo y el resto de la cuerda es negro.

¿Cómo puedo hacer esto en código?

Pedro
fuente
6
@EmptyStack Este ciertamente no es el caso ya que iOS 4 es compatible con NSAttributedString. Vea mi respuesta a continuación.
Mic Pringle

Respuestas:

223

La forma de hacerlo es usar NSAttributedStringasí:

NSMutableAttributedString *text = 
 [[NSMutableAttributedString alloc] 
   initWithAttributedString: label.attributedText];

[text addAttribute:NSForegroundColorAttributeName 
             value:[UIColor redColor] 
             range:NSMakeRange(10, 1)];
[label setAttributedText: text];

Creé una UILabel extensión para hacerlo .

João Costa
fuente
¿Puedo agregar objetivos en él? Thnaks
UserDev
¡Acabo de agregar su extensión a mi proyecto! ¡Gracias!
Zeb
Buena categoría para UILabel. Muchas gracias. Esta debería ser la respuesta aceptada.
Pradeep Reddy Kypa
63

He hecho esto creando un categoryforNSMutableAttributedString

-(void)setColorForText:(NSString*) textToFind withColor:(UIColor*) color
{
    NSRange range = [self.mutableString rangeOfString:textToFind options:NSCaseInsensitiveSearch];

    if (range.location != NSNotFound) {
        [self addAttribute:NSForegroundColorAttributeName value:color range:range];
    }
}

Úselo como

- (void) setColoredLabel
{
    NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"Here is a red blue and green text"];
    [string setColorForText:@"red" withColor:[UIColor redColor]];
    [string setColorForText:@"blue" withColor:[UIColor blueColor]];
    [string setColorForText:@"green" withColor:[UIColor greenColor]];
    mylabel.attributedText = string;
}

SWIFT 3

extension NSMutableAttributedString{
    func setColorForText(_ textToFind: String, with color: UIColor) {
        let range = self.mutableString.range(of: textToFind, options: .caseInsensitive)
        if range.location != NSNotFound {
            addAttribute(NSForegroundColorAttributeName, value: color, range: range)
        }
    }
}

USO

func setColoredLabel() {
    let string = NSMutableAttributedString(string: "Here is a red blue and green text")
    string.setColorForText("red", with: #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1))
    string.setColorForText("blue", with: #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1))
    string.setColorForText("green", with: #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1))
    mylabel.attributedText = string
}

SWIFT 4 @ kj13 Gracias por notificarnos

// If no text is send, then the style will be applied to full text
func setColorForText(_ textToFind: String?, with color: UIColor) {

    let range:NSRange?
    if let text = textToFind{
        range = self.mutableString.range(of: text, options: .caseInsensitive)
    }else{
        range = NSMakeRange(0, self.length)
    }
    if range!.location != NSNotFound {
        addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range!)
    }
}

He hecho más experimentos con atributos y a continuación están los resultados, aquí está el SOURCECODE

Aqui esta el resultado

Estilos

anoop4real
fuente
2
Necesita crear una nueva categoría para NSMutableAttributedString con el método ... de todos modos agregué esta muestra a github, puede tomarla
anoop4real
Pero necesito establecer el color de todo el alfabeto con incasesensitive en una cadena ... como toda "e" en color rojo de toda la cadena
Ravi Ojha
Sin @interface visible para 'NSMutableAttributedString' declara el selector 'setColorForText: withColor:'
ekashking
1
Recibí el error 'Uso del identificador no resuelto' NSForegroundColorAttributeName 'con Swift4.1, pero reemplazo' NSForegroundColorAttributeName 'por' NSAttributedStringKey.foregroundColor 'y construyo correctamente.
kj13
1
@ kj13 Gracias por notificarme, actualicé la respuesta y agregué algunos estilos más
anoop4real
25

Aqui tienes

NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:lblTemp.text];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0,5)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(5,6)];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(11,5)];
lblTemp.attributedText = string;
Hardik Mamtora
fuente
20

Rápido 4

// An attributed string extension to achieve colors on text.
extension NSMutableAttributedString {

    func setColor(color: UIColor, forText stringValue: String) {
       let range: NSRange = self.mutableString.range(of: stringValue, options: .caseInsensitive)
       self.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
    }

}

// Try it with label
let label = UILabel()
label.frame = CGRect(x: 70, y: 100, width: 260, height: 30)
let stringValue = "There are 5 results."
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: stringValue)
attributedString.setColor(color: UIColor.red, forText: "5")
label.font = UIFont.systemFont(ofSize: 26)
label.attributedText = attributedString
self.view.addSubview(label)

Resultado

ingrese la descripción de la imagen aquí


Swift 3

func setColoredLabel() {
        var string: NSMutableAttributedString = NSMutableAttributedString(string: "redgreenblue")
        string.setColor(color: UIColor.redColor(), forText: "red")
        string.setColor(color: UIColor.greenColor(), forText: "green")
        string.setColor(color: UIColor.blueColor(, forText: "blue")
        mylabel.attributedText = string
    }


func setColor(color: UIColor, forText stringValue: String) {
        var range: NSRange = self.mutableString.rangeOfString(stringValue, options: NSCaseInsensitiveSearch)
        if range != nil {
            self.addAttribute(NSForegroundColorAttributeName, value: color, range: range)
        }
    }

Resultado:

ingrese la descripción de la imagen aquí

Krunal
fuente
12
//NSString *myString = @"I have to replace text 'Dr Andrew Murphy, John Smith' ";
NSString *myString = @"Not a member?signin";

//Create mutable string from original one
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:myString];

//Fing range of the string you want to change colour
//If you need to change colour in more that one place just repeat it
NSRange range = [myString rangeOfString:@"signin"];
[attString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:(63/255.0) green:(163/255.0) blue:(158/255.0) alpha:1.0] range:range];

//Add it to the label - notice its not text property but it's attributeText
_label.attributedText = attString;
raju dontiboina
fuente
6

Desde iOS 6 , UIKit admite el dibujo de cadenas atribuidas, por lo que no se necesita extensión ni reemplazo.

De UILabel:

@property(nonatomic, copy) NSAttributedString *attributedText;

Solo necesita construir su NSAttributedString. Básicamente, hay dos formas:

  1. Agregue fragmentos de texto con los mismos atributos: para cada parte, cree una NSAttributedStringinstancia y añádalas a unaNSMutableAttributedString

  2. Cree texto con atributos a partir de una cadena simple y luego agregue atributos para rangos dados: busque el rango de su número (o lo que sea) y aplique un atributo de color diferente en eso.

Tricertops
fuente
6

Anups responde rápidamente. Se puede reutilizar de cualquier clase.

En archivo rápido

extension NSMutableAttributedString {

    func setColorForStr(textToFind: String, color: UIColor) {

        let range = self.mutableString.rangeOfString(textToFind, options:NSStringCompareOptions.CaseInsensitiveSearch);
        if range.location != NSNotFound {
            self.addAttribute(NSForegroundColorAttributeName, value: color, range: range);
        }

    }
}

En algún controlador de vista

let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: self.labelShopInYourNetwork.text!);
attributedString.setColorForStr("YOUR NETWORK", color: UIColor(red: 0.039, green: 0.020, blue: 0.490, alpha: 1.0));
self.labelShopInYourNetwork.attributedText = attributedString;
Deepak Thakur
fuente
4

Tener un UIWebView o más de un UILabel podría considerarse excesivo para esta situación.

Mi sugerencia sería usar TTTAttributedLabel, que es un reemplazo directo de UILabel que admite NSAttributedString . Esto significa que puede aplicar muy fácilmente diferentes estilos a diferentes rangos en una cadena.

Mic Pringle
fuente
3

JTAttributedLabel (por mystcolor) le permite usar el soporte de cadenas atribuidas en UILabel bajo iOS 6 y al mismo tiempo su clase JTAttributedLabel bajo iOS 5 a través de su JTAutoLabel.

Johan Kool
fuente
2

Existe una solución Swift 3.0

extension UILabel{


    func setSubTextColor(pSubString : String, pColor : UIColor){
        let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: self.text!);
        let range = attributedString.mutableString.range(of: pSubString, options:NSString.CompareOptions.caseInsensitive)
        if range.location != NSNotFound {
            attributedString.addAttribute(NSForegroundColorAttributeName, value: pColor, range: range);
        }
        self.attributedText = attributedString

    }
}

Y hay un ejemplo de llamada:

let colorString = " (string in red)"
self.mLabel.text = "classic color" + colorString
self.mLabel.setSubTextColor(pSubString: colorString, pColor: UIColor.red)
Kevin ABRIOUX
fuente
Hola, ¿cómo hago esto si quiero agregar dos cadenas de colores diferentes? Intenté usar su ejemplo y agregar otro, pero todavía solo colorea uno de ellos ..
Erik Auranaune
Pruebe esto: let colorString = "(cadena en rojo)" let colorStringGreen = "(cadena en verde)" self.mLabel.text = "color clásico" + colorString + colorStringGreen self.mLabel.setSubTextColor (pSubString: colorString, pColor: UIColor .red) self.mLabel.setSubTextColor (pSubString: colorStringGreen, pColor: UIColor.green)
Kevin ABRIOUX
Esto es extraño, todavía no cambia ambos: s24.postimg.org/ds0rpyyut/… .
Erik Auranaune
Un problema es que si las dos cadenas son iguales, solo colorea una de ellas, mira aquí: pastebin.com/FJZJTpp3 . ¿También tienes una solución para esto?
Erik Auranaune
2

Swift 4 y superior: inspirada en la solución de anoop4real , aquí hay una extensión de cadena que se puede usar para generar texto con 2 colores diferentes.

extension String {

    func attributedStringForPartiallyColoredText(_ textToFind: String, with color: UIColor) -> NSMutableAttributedString {
        let mutableAttributedstring = NSMutableAttributedString(string: self)
        let range = mutableAttributedstring.mutableString.range(of: textToFind, options: .caseInsensitive)
        if range.location != NSNotFound {
            mutableAttributedstring.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
        }
        return mutableAttributedstring
    }
}

El siguiente ejemplo cambia el color del asterisco a rojo y conserva el color de la etiqueta original para el texto restante.

label.attributedText = "Enter username *".attributedStringForPartiallyColoredText("*", with: #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1))
Disidente
fuente
2

Mi respuesta también tiene la opción de colorear todas las ocurrencias de un texto, no solo una ocurrencia del mismo: "wa ba wa ba dubdub", puede colorear todas las ocurrencias de wa no solo la primera ocurrencia como la respuesta aceptada.

extension NSMutableAttributedString{
    func setColorForText(_ textToFind: String, with color: UIColor) {
        let range = self.mutableString.range(of: textToFind, options: .caseInsensitive)
        if range.location != NSNotFound {
            addAttribute(NSForegroundColorAttributeName, value: color, range: range)
        }
    }

    func setColorForAllOccuranceOfText(_ textToFind: String, with color: UIColor) {
        let inputLength = self.string.count
        let searchLength = textToFind.count
        var range = NSRange(location: 0, length: self.length)

        while (range.location != NSNotFound) {
            range = (self.string as NSString).range(of: textToFind, options: [], range: range)
            if (range.location != NSNotFound) {
                self.addAttribute(NSForegroundColorAttributeName, value: color, range: NSRange(location: range.location, length: searchLength))
                range = NSRange(location: range.location + range.length, length: inputLength - (range.location + range.length))
            }
        }
    }
}

Ahora puedes hacer esto:

let message = NSMutableAttributedString(string: "wa ba wa ba dubdub")
message.setColorForText(subtitle, with: UIColor.red) 
// or the below one if you want all the occurrence to be colored 
message.setColorForAllOccuranceOfText("wa", with: UIColor.red) 
// then you set this attributed string to your label :
lblMessage.attributedText = message
Compilador de Alsh
fuente
¿Y cómo puedo usarlo?
pableiros
1
Actualicé mi respuesta, que tenga un buen día :)
Compilador de Alsh
1

Para los usuarios de Xamarin , tengo un método C # estático en el que paso una matriz de cadenas, una matriz de UIColours y una matriz de UIFonts (deberán coincidir en longitud). Luego, la cadena atribuida se devuelve.

ver:

public static NSMutableAttributedString GetFormattedText(string[] texts, UIColor[] colors, UIFont[] fonts)
    {

        NSMutableAttributedString attrString = new NSMutableAttributedString(string.Join("", texts));
        int position = 0;

        for (int i = 0; i < texts.Length; i++)
        {
            attrString.AddAttribute(new NSString("NSForegroundColorAttributeName"), colors[i], new NSRange(position, texts[i].Length));

            var fontAttribute = new UIStringAttributes
            {
                Font = fonts[i]
            };

            attrString.AddAttributes(fontAttribute, new NSRange(position, texts[i].Length));

            position += texts[i].Length;
        }

        return attrString;

    }
Campeón Craig
fuente
1

En mi caso, estoy usando Xcode 10.1. Existe la opción de cambiar entre texto sin formato y texto atribuido en el texto de la etiqueta en Interface Builder

ingrese la descripción de la imagen aquí

Espero que esto pueda ayudar a alguien más ...!

BharathRao
fuente
2
Parece que XCode 11.0 rompió el editor de texto atribuido. Entonces, intenté usar TextEdit para crear el texto, luego lo pegué en Xcode y funcionó sorprendentemente bien.
Brainware
0
extension UILabel{

    func setSubTextColor(pSubString : String, pColor : UIColor){


        let attributedString: NSMutableAttributedString = self.attributedText != nil ? NSMutableAttributedString(attributedString: self.attributedText!) : NSMutableAttributedString(string: self.text!);


        let range = attributedString.mutableString.range(of: pSubString, options:NSString.CompareOptions.caseInsensitive)
        if range.location != NSNotFound {
            attributedString.addAttribute(NSForegroundColorAttributeName, value: pColor, range: range);
        }
        self.attributedText = attributedString

    }
}
Dipak Panchasara
fuente
0

Mi propia solución fue creada con un método como el siguiente:

-(void)setColorForText:(NSString*) textToFind originalText:(NSString *)originalString withColor:(UIColor*)color andLabel:(UILabel *)label{

NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:originalString];
NSRange range = [originalString rangeOfString:textToFind];

[attString addAttribute:NSForegroundColorAttributeName value:color range:range];

label.attributedText = attString;

if (range.location != NSNotFound) {
    [attString addAttribute:NSForegroundColorAttributeName value:color range:range];
}
label.attributedText = attString; }

Funcionó con un solo color diferente en el mismo texto, pero puedes adaptarlo fácilmente a más colores en la misma oración.

shontauro
fuente
0

Al usar el siguiente código, puede establecer varios colores según la palabra.

NSMutableArray * array = [[NSMutableArray alloc] initWithObjects:@"1 ball",@"2 ball",@"3 ball",@"4 ball", nil];    
NSMutableAttributedString *attStr = [[NSMutableAttributedString alloc] init];
for (NSString * str in array)
 {
    NSMutableAttributedString * textstr = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ ,",str] attributes:@{NSForegroundColorAttributeName :[self getRandomColor]}];
     [attStr appendAttributedString:textstr];
  }
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(10, 300, 300, 30)];
lab.attributedText = attStr;
[self.view addSubview:lab];

-(UIColor *) getRandomColor
{
   CGFloat redcolor = arc4random() % 255 / 255.0;
   CGFloat greencolor = arc4random() % 255 / 255.0;
   CGFloat bluencolor = arc4random() % 255 / 255.0;
   return  [UIColor colorWithRed:redcolor green:greencolor blue:bluencolor alpha:1.0];
}
Hari c
fuente
0

SwiftRichStringfunciona perfecto! Puede usar +para concatenar dos cadenas con atributos

fujianjin6471
fuente