Modification de la couleur d'un texte spécifique à l'aide de NSMutableAttributedString dans Swift

100

Le problème que je rencontre est que je veux pouvoir changer le textColor de certains textes dans un TextView. J'utilise une chaîne concaténée et je veux juste les chaînes que j'ajoute dans le texte du TextView. Il semble que ce que je veux utiliser NSMutableAttributedString, mais je ne trouve aucune ressource sur la façon de l'utiliser dans Swift. Ce que j'ai jusqu'à présent, c'est quelque chose comme ça:

let string = "A \(stringOne) with \(stringTwo)"
var attributedString = NSMutableAttributedString(string: string)
textView.attributedText = attributedString

À partir de là, je sais que je dois trouver la plage de mots dont la couleur de texte doit être modifiée, puis les ajouter à la chaîne attribuée. Ce que j'ai besoin de savoir, c'est comment trouver les chaînes correctes à partir de la chaîne attribuée, puis modifier leur textColor.

Comme j'ai une note trop basse, je ne peux pas répondre à ma propre question, mais voici la réponse que j'ai trouvée

J'ai trouvé ma propre réponse en traduisant en traduisant du code de

Modifier les attributs des sous-chaînes dans un NSAttributedString

Voici l'exemple d'implémentation dans Swift:

let string = "A \(stringOne) and \(stringTwo)"
var attributedString = NSMutableAttributedString(string:string)

let stringOneRegex = NSRegularExpression(pattern: nameString, options: nil, error: nil)
let stringOneMatches = stringOneRegex.matchesInString(longString, options: nil, range: NSMakeRange(0, attributedString.length))
for stringOneMatch in stringOneMatches {
    let wordRange = stringOneMatch.rangeAtIndex(0)
    attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.nameColor(), range: wordRange)
}

textView.attributedText = attributedString

Puisque je souhaite changer le textColor de plusieurs chaînes, je vais créer une fonction d'assistance pour gérer cela, mais cela fonctionne pour changer le textColor.

richyrich24
la source
Savez-vous comment le faire en Objective-C? Avez-vous tenté de réécrire ce même code dans Swift?
Aaron Brager
Voici une très bonne réponse: stackoverflow.com/a/37992022/426571
el_quick

Réponses:

110

Je vois que vous avez un peu répondu à la question, mais pour fournir une manière un peu plus concise sans utiliser de regex pour répondre à la question du titre:

Pour changer la couleur d'une longueur de texte, vous devez connaître l'index de début et de fin des caractères à colorier dans la chaîne, par exemple

var main_string = "Hello World"
var string_to_color = "World"

var range = (main_string as NSString).rangeOfString(string_to_color)

Ensuite, vous convertissez en chaîne attribuée et utilisez 'ajouter un attribut' avec NSForegroundColorAttributeName:

var attributedString = NSMutableAttributedString(string:main_string)
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor() , range: range)

Une liste d'autres attributs standard que vous pouvez définir se trouve dans la documentation d'Apple

james_alvarez
la source
20
NSColor est OSX uniquement - utilisez UIColor pour IOS
Steve O'Connor
1
Que faire si j'ai var main_string = "Hello World Hello World Hello World" et que j'ai besoin d'appliquer la couleur sur "World" dans toute la chaîne?
msmq
main_string, string_to_coloret rangen'ont jamais été mutés. Pensez à les changer en letconstant?
Cesare
Belle solution. Vous avez sauvé ma journée.
Sagar Chauhan
106

SWIFT 5

let main_string = "Hello World"
let string_to_color = "World"

let range = (main_string as NSString).range(of: string_to_color)

let attribute = NSMutableAttributedString.init(string: main_string)
attribute.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)


txtfield1 = UITextField.init(frame:CGRect(x:10 , y:20 ,width:100 , height:100))
txtfield1.attributedText = attribute

SWIFT 4.2

 let txtfield1 :UITextField!

    let main_string = "Hello World"
    let string_to_color = "World"

    let range = (main_string as NSString).range(of: string_to_color)

    let attribute = NSMutableAttributedString.init(string: main_string)
    attribute.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.red , range: range)


    txtfield1 = UITextField.init(frame:CGRect(x:10 , y:20 ,width:100 , height:100))
    txtfield1.attributedText = attribute
Kishore Kumar
la source
Que faire si la chaîne est grande et contient de nombreux mots dupliqués (similaires). va gamme (de: ...) fonctionne?
Hatim le
44

Mise à jour Swift 2.1:

 let text = "We tried to make this app as most intuitive as possible for you. If you have any questions don't hesitate to ask us. For a detailed manual just click here."
 let linkTextWithColor = "click here"

 let range = (text as NSString).rangeOfString(linkTextWithColor)

 let attributedString = NSMutableAttributedString(string:text)
 attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor() , range: range)

 self.helpText.attributedText = attributedString

self.helpTextest un UILabelexutoire.

Chris
la source
1
Oh Chris, tu es mon héros. Je recherche ce bloc de code exactement depuis longtemps.
Pan Mluvčí
@chris. Je veux changer la chaîne nsmutableattributed dans textview, est-ce possible
Uma Madhavi
cela fonctionne pour un seul mot.Mais dans ma chaîne, il y a plusieurs mots, c'est le changement de couleur, mais j'écris après ce mot de couleur rouge.La couleur de ce mot est également rouge.Vous pouvez également donner une solution si vous avez.
Dhaval Solanki
Merci de votre aide!
ssowri1
18

Swift 4.2 et Swift 5 colorisent des parties de la corde.

Un moyen très simple d'utiliser NSMutableAttributedString tout en étendant le String. Cela peut également être utilisé pour colorer plus d'un mot dans toute la chaîne.

Ajouter un nouveau fichier pour les extensions, Fichier -> Nouveau -> Fichier Swift avec un nom par ex. "NSAttributedString + TextColouring" et ajoutez le code

import UIKit

extension String {
    func attributedStringWithColor(_ strings: [String], color: UIColor, characterSpacing: UInt? = nil) -> NSAttributedString {
        let attributedString = NSMutableAttributedString(string: self)
        for string in strings {
            let range = (self as NSString).range(of: string)
            attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range)
        }

        guard let characterSpacing = characterSpacing else {return attributedString}

        attributedString.addAttribute(NSAttributedString.Key.kern, value: characterSpacing, range: NSRange(location: 0, length: attributedString.length))

        return attributedString
    }
}

Vous pouvez maintenant utiliser globalement sur n'importe quel viewcontroller de votre choix:

let attributedWithTextColor: NSAttributedString = "Doc, welcome back :)".attributedStringWithColor(["Doc", "back"], color: UIColor.black)

myLabel.attributedText = attributedWithTextColor

Exemple d'utilisation de la coloration de texte avec Swift 4

Doci
la source
11

La réponse est déjà donnée dans les articles précédents mais j'ai une manière différente de le faire

Swift 3x:

var myMutableString = NSMutableAttributedString()

myMutableString = NSMutableAttributedString(string: "Your full label textString")

myMutableString.setAttributes([NSFontAttributeName : UIFont(name: "HelveticaNeue-Light", size: CGFloat(17.0))!
        , NSForegroundColorAttributeName : UIColor(red: 232 / 255.0, green: 117 / 255.0, blue: 40 / 255.0, alpha: 1.0)], range: NSRange(location:12,length:8)) // What ever range you want to give

yourLabel.attributedText = myMutableString

J'espère que cela aide n'importe qui!

Anurag Sharma
la source
@UmaMadhavi Quelle est votre exigence exactement?
Anurag Sharma
Je souhaite modifier la taille et la couleur de la police dans Textview. Je l'obtiens dans nsmutableattributedstring.
Uma Madhavi
@UmaMadhavi vérifier cette link1 et lien2 . Cela peut être utile!
Anurag Sharma
Se bloque si la police n'est pas disponible.
SafeFastExpressive
10

La réponse de Chris m'a beaucoup aidé, alors j'ai utilisé son approche et je suis devenue une fonction que je peux réutiliser. Cela me permet d'assigner une couleur à une sous-chaîne tout en donnant au reste de la chaîne une autre couleur.

static func createAttributedString(fullString: String, fullStringColor: UIColor, subString: String, subStringColor: UIColor) -> NSMutableAttributedString
{
    let range = (fullString as NSString).rangeOfString(subString)
    let attributedString = NSMutableAttributedString(string:fullString)
    attributedString.addAttribute(NSForegroundColorAttributeName, value: fullStringColor, range: NSRange(location: 0, length: fullString.characters.count))
    attributedString.addAttribute(NSForegroundColorAttributeName, value: subStringColor, range: range)
    return attributedString
}
ghostatron
la source
6

Swift 4.1

NSAttributedStringKey.foregroundColor

par exemple si vous souhaitez changer de police dans NavBar:

self.navigationController?.navigationBar.titleTextAttributes = [ NSAttributedStringKey.font: UIFont.systemFont(ofSize: 22), NSAttributedStringKey.foregroundColor: UIColor.white]
swift2geek
la source
6

Vous pouvez utiliser cette extension, je la teste

rapide 4.2

import Foundation
import UIKit

extension NSMutableAttributedString {

    convenience init (fullString: String, fullStringColor: UIColor, subString: String, subStringColor: UIColor) {
           let rangeOfSubString = (fullString as NSString).range(of: subString)
           let rangeOfFullString = NSRange(location: 0, length: fullString.count)//fullString.range(of: fullString)
           let attributedString = NSMutableAttributedString(string:fullString)
           attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: fullStringColor, range: rangeOfFullString)
           attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: subStringColor, range: rangeOfSubString)

           self.init(attributedString: attributedString)
   }

}
Amr en colère
la source
4

Swift 2.2

var myMutableString = NSMutableAttributedString()

myMutableString = NSMutableAttributedString(string: "1234567890", attributes: [NSFontAttributeName:UIFont(name: kDefaultFontName, size: 14.0)!])

myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor(red: 0.0/255.0, green: 125.0/255.0, blue: 179.0/255.0, alpha: 1.0), range: NSRange(location:0,length:5))

self.lblPhone.attributedText = myMutableString
Sarabjit Singh
la source
J'obtiens une erreur lorsque je fais cela. Je pense que tu veux ça sans .CGColor.
Bjorn Roche
@SarabjitSingh. comment est-ce possible pour textview
Uma Madhavi
@UmaMadhavi ... Il vous suffit d'ajouter self.textView.attributedText = myMutableString ..... Cela fonctionnera ...
Sarabjit Singh
4

Le moyen le plus simple de créer des étiquettes avec un style différent tel que la couleur, la police, etc. est d'utiliser la propriété "Attribuée" dans l'inspecteur d'attributs. Choisissez simplement une partie du texte et modifiez-la comme vous le souhaitez

entrez la description de l'image ici

jMelvins
la source
1
Sous réserve de ne pas changer les cordes par programme
Alejandro Cumpa
4

Basé sur les réponses avant de créer une extension de chaîne

extension String {

func highlightWordsIn(highlightedWords: String, attributes: [[NSAttributedStringKey: Any]]) -> NSMutableAttributedString {
     let range = (self as NSString).range(of: highlightedWords)
     let result = NSMutableAttributedString(string: self)

     for attribute in attributes {
         result.addAttributes(attribute, range: range)
     }

     return result
    }
}

Vous pouvez transmettre les attributs du texte à la méthode

Appelez comme ça

  let attributes = [[NSAttributedStringKey.foregroundColor:UIColor.red], [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 17)]]
  myLabel.attributedText = "This is a text".highlightWordsIn(highlightedWords: "is a text", attributes: attributes)
kuzdu
la source
4

Swift 4.1

J'ai changé de cela dans Swift 3

let str = "Welcome "
let welcomeAttribute = [ NSForegroundColorAttributeName: UIColor.blue()]
let welcomeAttrString = NSMutableAttributedString(string: str, attributes: welcomeAttribute)

Et cela dans Swift 4.0

let str = "Welcome "
let welcomeAttribute = [ NSAttributedStringKey.foregroundColor: UIColor.blue()]
let welcomeAttrString = NSMutableAttributedString(string: str, attributes: welcomeAttribute)

vers Swift 4.1

let str = "Welcome "
let welcomeAttribute = [ NSAttributedStringKey(rawValue: NSForegroundColorAttributeName): UIColor.blue()]
let welcomeAttrString = NSMutableAttributedString(string: str, attributes: welcomeAttribute)

Fonctionne bien

niravdesai21
la source
Cela change la chaîne entière? C'est le plus lisible pour moi, mais y a-t-il un moyen de ne changer que des mots spécifiques dans la chaîne comme l'OP l'a demandé.
Moondra
3

rapide 4.2

    let textString = "Hello world"
    let range = (textString as NSString).range(of: "world")
    let attributedString = NSMutableAttributedString(string: textString)

    attributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.red, range: range)
    self.textUIlable.attributedText = attributedString
Giang
la source
2

Pour tous ceux qui recherchent " Appliquer une couleur spécifique à plusieurs mots dans le texte ", nous pouvons le faire en utilisant NSRegularExpression

 func highlight(matchingText: String, in text: String) {
    let attributedString  = NSMutableAttributedString(string: text)
    if let regularExpression = try? NSRegularExpression(pattern: "\(matchingText)", options: .caseInsensitive) {
        let matchedResults = regularExpression.matches(in: text, options: [], range: NSRange(location: 0, length: attributedString.length))
        for matched in matchedResults {
             attributedString.addAttributes([NSAttributedStringKey.backgroundColor : UIColor.yellow], range: matched.range)

        }
        yourLabel.attributedText = attributedString
    }
}

Lien de référence: https://gist.github.com/aquajach/4d9398b95a748fd37e88

cgeek
la source
Est-il possible d'utiliser votre code dans l'application MacOS Cocoa? J'ai essayé de l'utiliser dans mon projet Cocoa, mais il n'y a pas de .attributedText dans Cocoa NSTextView.
CaOs433
2

Cela pourrait être un travail pour vous

let main_string = " User not found,Want to review ? Click here"
    let string_to_color = "Click here"

    let range = (main_string as NSString).range(of: string_to_color)

    let attribute = NSMutableAttributedString.init(string: main_string)
    attribute.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue , range: range)

    lblClickHere.attributedText = attribute
Davender Verma
la source
1
Bien que cet extrait de code puisse être la solution, inclure une explication contribue vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question aux lecteurs à l'avenir, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
HMD
2

Avec cette fonction simple, vous pouvez attribuer le texte et mettre en évidence le mot choisi.

Vous pouvez également changer UITextView en UILabel , etc.

func highlightBoldWordAtLabel(textViewTotransform: UITextView, completeText: String, wordToBold: String){
    textViewToTransform.text = completeText
    let range = (completeText as NSString).range(of: wordToBold)
    let attribute = NSMutableAttributedString.init(string: completeText)

    attribute.addAttribute(NSAttributedString.Key.font, value: UIFont.boldSystemFont(ofSize: 16), range: range)
    attribute.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.black , range: range)
    textViewToTransform.attributedText = attribute
}
Développeur Dan
la source
1

Pour changer la couleur de la couleur de la police, sélectionnez d'abord attribué au lieu de uni comme dans l'image ci-dessous

Vous devez ensuite sélectionner le texte dans le champ attribué, puis sélectionner le bouton de couleur sur le côté droit des alignements. Cela changera la couleur.

Kingsley Mitchell
la source
1

Vous pouvez utiliser cette méthode. J'ai implémenté cette méthode dans ma classe utilitaire commune pour accéder globalement.

func attributedString(with highlightString: String, normalString: String, highlightColor: UIColor) -> NSMutableAttributedString {
    let attributes = [NSAttributedString.Key.foregroundColor: highlightColor]
    let attributedString = NSMutableAttributedString(string: highlightString, attributes: attributes)
    attributedString.append(NSAttributedString(string: normalString))
    return attributedString
}
nitin.agam
la source
0

Si vous utilisez Swift 3x et UITextView, peut-être que NSForegroundColorAttributeName ne fonctionnera pas (cela n'a pas fonctionné pour moi quelle que soit l'approche que j'ai essayée).

Donc, après quelques recherches, j'ai trouvé une solution.

//Get the textView somehow
let textView = UITextView()
//Set the attributed string with links to it
textView.attributedString = attributedString
//Set the tint color. It will apply to the link only
textView.tintColor = UIColor.red
Mcastro
la source
0

Un moyen très simple de le faire.

let text = "This is a colorful attributed string"
let attributedText = 
NSMutableAttributedString.getAttributedString(fromString: text)
attributedText.apply(color: .red, subString: "This")
//Apply yellow color on range
attributedText.apply(color: .yellow, onRange: NSMakeRange(5, 4))

Pour plus de détails, cliquez ici: https://github.com/iOSTechHub/AttributedString

Ashish Chauhan
la source
0

Vous devez modifier les paramètres d'affichage du texte, pas les paramètres de la chaîne attribuée

textView.linkTextAttributes = [
        NSAttributedString.Key.foregroundColor: UIColor.red,
        NSAttributedString.Key.underlineColor: UIColor.red,
        NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue
    ]
Maxvale
la source
0

Veuillez vérifier cocoapod Prestyler :

Prestyler.defineRule("$", UIColor.orange)
label.attributedText = "This $text$ is orange".prestyled()
Kruiller
la source
0
extension String{
// to make text field mandatory * looks
mutating func markAsMandatoryField()-> NSAttributedString{

    let main_string = self
    let string_to_color = "*"
    let range = (main_string as NSString).range(of: string_to_color)
    print("The rang = \(range)")
    let attribute = NSMutableAttributedString.init(string: main_string)
    attribute.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.rgbColor(red: 255.0, green: 0.0, blue: 23.0) , range: range)
     return attribute
}

}

utilisez EmailLbl.attributedText = EmailLbl.text! .markAsMandatoryField ()

NSurajit
la source
0

Vous pouvez utiliser comme simple extension

extension String{

func attributedString(subStr: String) -> NSMutableAttributedString{
    let range = (self as NSString).range(of: subStr)
    let attributedString = NSMutableAttributedString(string:self)
    attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)
    
    return attributedString
  }
}

myLable.attributedText = fullStr.attributedString(subStr: strToChange)

  
Waliyan
la source