Cambiar el color de un texto específico usando NSMutableAttributedString en Swift

100

El problema que tengo es que quiero poder cambiar el color de texto de cierto texto en un TextView. Estoy usando una cadena concatenada y solo quiero las cadenas que agrego al texto de TextView. Parece que lo que quiero usar es NSMutableAttributedString, pero no encuentro ningún recurso sobre cómo usar esto en Swift. Lo que tengo hasta ahora es algo como esto:

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

Desde aquí, sé que necesito encontrar el rango de palabras que deben cambiar su color de texto y luego agregarlas a la cadena atribuida. Lo que necesito saber es cómo encontrar las cadenas correctas del atributoString y luego cambiar su color de texto.

Como tengo una calificación demasiado baja, no puedo responder mi propia pregunta, pero aquí está la respuesta que encontré

Encontré mi propia respuesta traduciendo de la traducción de un código de

Cambiar atributos de subcadenas en una NSAttributedString

Aquí está el ejemplo de implementación en 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

Como quiero cambiar el color de texto de varias cadenas, crearé una función auxiliar para manejar esto, pero esto funciona para cambiar el color de texto.

richyrich24
fuente
¿Sabes cómo hacerlo en Objective-C? ¿Ha intentado reescribir ese mismo código en Swift?
Aaron Brager
Aquí hay una muy buena respuesta: stackoverflow.com/a/37992022/426571
el_quick

Respuestas:

110

Veo que ha respondido la pregunta de alguna manera, pero para proporcionar una forma un poco más concisa sin usar expresiones regulares para responder a la pregunta del título:

Para cambiar el color de una longitud de texto, debe conocer el índice de inicio y finalización de los caracteres que se van a colorear en la cadena, por ejemplo

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

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

Luego, convierte a una cadena atribuida y usa 'agregar atributo' con NSForegroundColorAttributeName:

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

Puede encontrar una lista de otros atributos estándar que puede establecer en la documentación de Apple

james_alvarez
fuente
20
NSColor es solo para OSX - use UIColor para IOS
Steve O'Connor
1
¿Qué sucede si tengo var main_string = "Hola mundo Hola mundo Hola mundo" y necesito aplicar color en "Mundo" en toda la cadena?
msmq
main_string, string_to_colory rangenunca fueron mutados. ¿Considera cambiarlos a letconstante?
Cesare
Buena solucion. Me has salvado el día.
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
fuente
¿Qué pasa si la cadena es grande y tiene muchas palabras duplicadas (similares)? ¿Funciona el rango (de: ...)?
Hatim
44

Actualización 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.helpTextes una UILabelsalida.

Chris
fuente
1
Oh Chris, eres mi héroe. Estoy buscando este bloque de código exactamente durante mucho tiempo.
Pan Mluvčí
@chris. Quiero cambiar la cadena nsmutableattributed en la vista de texto, ¿es eso posible?
Uma Madhavi
funciona para una sola palabra. pero en mi cadena hay varias palabras, es un cambio de color, pero luego escribo después de esa palabra de color rojo que el color de la palabra también es rojo. Entonces, ¿puede dar alguna solución si la tiene?
Dhaval Solanki
¡Gracias por tu ayuda!
ssowri1
18

Swift 4.2 y Swift 5 colorean partes de la cuerda.

Una forma muy fácil de usar NSMutableAttributedString mientras se extiende String. Esto también se puede utilizar para colorear más de una palabra en toda la cadena.

Agregue un nuevo archivo para extensiones, Archivo -> Nuevo -> Archivo Swift con nombre por ej. "NSAttributedString + TextColouring" y agregue el código

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

Ahora puede usar globalmente en cualquier controlador de vista que desee:

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

myLabel.attributedText = attributedWithTextColor

Ejemplo de uso de coloración de texto con swift 4

Doci
fuente
11

La respuesta ya se dio en publicaciones anteriores, pero tengo una forma diferente de hacer esto

Rápido 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

¡Espero que esto ayude a alguien!

Anurag Sharma
fuente
@UmaMadhavi ¿Cuál es exactamente su requisito?
Anurag Sharma
Quiero cambiar el tamaño y el color de la fuente en la vista de texto. Lo estoy obteniendo en nsmutableattributedstring.
Uma Madhavi
@UmaMadhavi mira este link1 y link2 . ¡Puede ser útil!
Anurag Sharma
Se bloquea si la fuente no está disponible.
SafeFastExpressive
10

La respuesta de Chris fue de gran ayuda para mí, así que usé su enfoque y lo convertí en una función que puedo reutilizar. Esto me permite asignar un color a una subcadena mientras le doy al resto de la cadena otro color.

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
fuente
6

Swift 4.1

NSAttributedStringKey.foregroundColor

por ejemplo, si desea cambiar la fuente en NavBar:

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

Puedes usar esta extensión, la pruebo

rápido 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 enojado
fuente
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
fuente
Recibo un error cuando hago esto. Creo que quieres esto sin .CGColor.
Bjorn Roche
@SarabjitSingh. ¿Cómo es posible esto para textview?
Uma Madhavi
@UmaMadhavi ... Solo necesita agregar self.textView.attributedText = myMutableString ..... Funcionará ...
Sarabjit Singh
4

La forma más fácil de hacer etiquetas con diferentes estilos como el color, la fuente, etc. es usar la propiedad "Atributos" en el Inspector de atributos. Simplemente elija parte del texto y cámbielo como desee

ingrese la descripción de la imagen aquí

jMelvins
fuente
1
Suponiendo que no estás cambiando las cadenas programáticamente
Alejandro Cumpa
4

Basado en las respuestas antes de crear una extensión de cadena

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

Puede pasar los atributos del texto al método

Llamar así

  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
fuente
4

Swift 4.1

He cambiado de esto en Swift 3

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

Y esto en Swift 4.0

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

a Swift 4.1

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

Funciona bien

niravdesai21
fuente
¿Esto está cambiando toda la cadena? Este es el más legible para mí, pero ¿hay alguna manera de cambiar solo palabras específicas dentro de la cadena como pidió el OP?
Moondra
3

rápido 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
fuente
2

Para todos los que buscan " Aplicar un color específico a varias palabras en el texto ", podemos hacerlo usando 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
    }
}

Enlace de referencia: https://gist.github.com/aquajach/4d9398b95a748fd37e88

friki
fuente
¿Es posible usar su código en la aplicación MacOS Cocoa? Intenté usarlo en mi proyecto de cocoa, pero no hay .attributedText en cocoa NSTextView.
CaOs433
2

Esto podría funcionar para ti

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
fuente
1
Si bien este fragmento de código puede ser la solución, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo a la pregunta para los lectores en el futuro, y es posible que esas personas no conozcan los motivos de su sugerencia de código.
HMD
2

Con esta sencilla función puedes asignar el texto y resaltar la palabra elegida.

También puede cambiar UITextView a 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
}
Desarrollador Dan
fuente
1

Para cambiar el color de la fuente, primero seleccione atribuido en lugar de simple como en la imagen de abajo

Luego, debe seleccionar el texto en el campo atribuido y luego seleccionar el botón de color en el lado derecho de las alineaciones. Esto cambiará el color.

Kingsley Mitchell
fuente
1

Puede utilizar este método. Implementé este método en mi clase de utilidad común para acceder globalmente.

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
fuente
0

Si está utilizando Swift 3x y UITextView, tal vez NSForegroundColorAttributeName no funcione (no me funcionó sin importar el enfoque que intenté).

Entonces, después de investigar un poco, encontré una solución.

//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
fuente
0

Manera súper fácil de hacer esto.

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

Para obtener más detalles, haga clic aquí: https://github.com/iOSTechHub/AttributedString

Ashish Chauhan
fuente
0

Necesita cambiar los parámetros de la vista de texto, no los parámetros de la cadena atribuida

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

Por favor, consulte Cocoapod Prestyler :

Prestyler.defineRule("$", UIColor.orange)
label.attributedText = "This $text$ is orange".prestyled()
Asesino
fuente
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
}

}

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

NSurajit
fuente
0

Puedes usar como extensión simple

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
fuente