UILabel avec texte de deux couleurs différentes

109

Je veux afficher une chaîne comme celle-ci dans un UILabel:

Il y a 5 résultats.

Où le numéro 5 est de couleur rouge et le reste de la chaîne est noir.

Comment puis-je faire cela dans le code?

Peter
la source
6
@EmptyStack Ce n'est certainement pas le cas puisque iOS 4 prend en charge NSAttributedString. Voir ma réponse ci-dessous.
Mic Pringle

Réponses:

223

La façon de le faire est d'utiliser NSAttributedStringcomme ceci:

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

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

J'ai créé une UILabel extension pour le faire .

João Costa
la source
Puis-je y ajouter des cibles. Thnaks
UserDev
Je viens d'ajouter votre extension à mon projet! THX!
Zeb
Belle catégorie pour UILabel. Merci beaucoup. Cela devrait être la réponse acceptée.
Pradeep Reddy Kypa
63

J'ai fait cela en créant un categorypourNSMutableAttributedString

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

Utilisez-le comme

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

USAGE

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 Merci de l'avoir notifié

// 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!)
    }
}

J'ai fait plus d'expériences avec les attributs et ci-dessous sont les résultats, voici le SOURCECODE

Voici le résultat

modes

anoop4real
la source
2
Vous devez créer une nouvelle catégorie pour NSMutableAttributedString avec la méthode ... de toute façon, j'ai ajouté cet exemple à github, vous pouvez le récupérer et le vérifier github.com/anoop4real/NSMutableAttributedString-Color
anoop4real
Mais j'ai besoin de définir la couleur de tous les alphabets avec incasensitive dans une chaîne .... comme tous les "e" dans la couleur rouge de la chaîne entière
Ravi Ojha
Aucune @interface visible pour 'NSMutableAttributedString' déclare le sélecteur 'setColorForText: withColor:'
ekashking
1
J'ai eu l'erreur «Utilisation de l'identificateur non résolu« NSForegroundColorAttributeName »avec Swift4.1, mais je remplace« NSForegroundColorAttributeName »par« NSAttributedStringKey.foregroundColor »et je construis correctement.
kj13
1
@ kj13 Merci d'avoir averti, j'ai mis à jour la réponse et ajouté quelques styles supplémentaires
anoop4real
25

Voici

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
la source
20

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

Résultat

entrez la description de l'image ici


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

Résultat:

entrez la description de l'image ici

Krunal
la source
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
la source
6

Depuis iOS 6 , UIKit prend en charge le dessin de chaînes attribuées, aucune extension ou remplacement n'est donc nécessaire.

De UILabel:

@property(nonatomic, copy) NSAttributedString *attributedText;

Il vous suffit de créer votre fichier NSAttributedString. Il existe essentiellement deux façons:

  1. Ajoutez des morceaux de texte avec les mêmes attributs - pour chaque partie, créez une NSAttributedStringinstance et ajoutez-les à uneNSMutableAttributedString

  2. Créez un texte attribué à partir d'une chaîne simple, puis ajoutez un attribut pour des plages données - trouvez la plage de votre numéro (ou autre) et appliquez un attribut de couleur différent à cela.

Tricertops
la source
6

Anups répond rapidement. Peut être réutilisé à partir de n'importe quelle classe.

Dans le fichier rapide

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

    }
}

Dans certains contrôleur de vue

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
la source
4

Avoir un UIWebView ou plus d'un UILabel pourrait être considéré comme excessif pour cette situation.

Ma suggestion serait d'utiliser TTTAttributedLabel, qui remplace UILabel qui prend en charge NSAttributedString . Cela signifie que vous pouvez très facilement appliquer différents styles à différentes plages d'une chaîne.

Mic Pringle
la source
3

JTAttributedLabel (par mystcolor) vous permet d'utiliser le support des chaînes attribuées dans UILabel sous iOS 6 et en même temps sa classe JTAttributedLabel sous iOS 5 via son JTAutoLabel.

Johan Kool
la source
2

Il existe une solution 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

    }
}

Et il y a un exemple d'appel:

let colorString = " (string in red)"
self.mLabel.text = "classic color" + colorString
self.mLabel.setSubTextColor(pSubString: colorString, pColor: UIColor.red)
Kevin ABRIOUX
la source
Salut, comment puis-je faire cela si je veux ajouter deux colorStrings différents? J'ai essayé d'utiliser votre exemple et d'en ajouter un autre, mais cela ne colore que l'un d'entre eux.
Erik Auranaune
Essayez ceci: let colorString = "(string in red)" let colorStringGreen = "(string in green)" self.mLabel.text = "classic color" + colorString + colorStringGreen self.mLabel.setSubTextColor (pSubString: colorString, pColor: UIColor .red) self.mLabel.setSubTextColor (pSubString: colorStringGreen, pColor: UIColor.green)
Kevin ABRIOUX
C'est étrange, cela ne change toujours pas les deux: s24.postimg.org/ds0rpyyut/… .
Erik Auranaune
Un problème est que si les deux chaînes sont identiques, cela ne colore qu'une seule d'entre elles, regardez ici: pastebin.com/FJZJTpp3 . Vous avez une solution pour cela aussi?
Erik Auranaune
2

Swift 4 et supérieur: Inspiré de la solution anoop4real , voici une extension String qui peut être utilisée pour générer du texte avec 2 couleurs différentes.

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

L'exemple suivant change la couleur de l'astérisque en rouge tout en conservant la couleur de l'étiquette d'origine pour le texte restant.

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

Ma réponse a également la possibilité de colorer toutes les occurrences d'un texte non seulement une occurrence de celui-ci: "wa ba wa ba dubdub", vous pouvez colorier toutes les occurrences de wa non seulement la première occurrence comme la réponse acceptée.

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

Vous pouvez maintenant faire ceci:

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
Compilateur Alsh
la source
Et comment puis-je l'utiliser?
pableiros
1
Mis à jour ma réponse, passez une bonne journée :)
compilateur Alsh
1

Pour les utilisateurs de Xamarin , j'ai un C # statique méthode laquelle je passe un tableau de chaînes, un tableau d'UIColours et un tableau d'UIFont (ils devront correspondre en longueur). La chaîne attribuée est ensuite renvoyée.

voir:

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;

    }
Craig Champion
la source
1

Dans mon cas, j'utilise Xcode 10.1. Il existe une option permettant de basculer entre le texte brut et le texte attribué dans le texte d'étiquette dans Interface Builder

entrez la description de l'image ici

J'espère que cela peut aider quelqu'un d'autre ..!

BharathRao
la source
2
Il semble que XCode 11.0 a cassé l'éditeur de texte attribué. J'ai donc essayé d'utiliser TextEdit pour créer le texte, puis je l'ai collé dans Xcode et cela a étonnamment bien fonctionné.
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
la source
0

Ma propre solution a été créée une méthode comme la suivante:

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

Cela fonctionnait avec une seule couleur différente dans le même texte, mais vous pouvez l'adapter facilement à plusieurs couleurs dans la même phrase.

Shontauro
la source
0

En utilisant le code ci-dessous, vous pouvez définir plusieurs couleurs en fonction du mot.

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
la source
0

SwiftRichStringfonctionne parfaitement! Vous pouvez utiliser +pour concaténer deux chaînes attribuées

fujianjin6471
la source