Alterar a cor do texto específico usando NSMutableAttributedString em Swift


100

O problema que estou tendo é que quero ser capaz de alterar o textColor de determinado texto em um TextView. Estou usando uma string concatenada e só quero as strings que estou acrescentando ao texto do TextView. Parece que o que eu quero usar é NSMutableAttributedString, mas não estou encontrando recursos de como usar isso no Swift. O que eu tenho até agora é algo assim:

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

A partir daqui, sei que preciso encontrar o intervalo de palavras que precisam ter seu textColor alterado e, em seguida, adicioná-los à string atribuída. O que eu preciso saber é como encontrar as strings corretas de attributeString e, em seguida, alterar sua textColor.

Como eu tenho uma classificação muito baixa, não posso responder minha própria pergunta, mas aqui está a resposta que encontrei

Eu encontrei minha própria resposta traduzindo da tradução de algum código de

Alterar atributos de substrings em um NSAttributedString

Aqui está o exemplo de implementação em 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

Já que estou querendo mudar o textColor de várias Strings, farei uma função auxiliar para lidar com isso, mas isso funciona para mudar o textColor.


Você sabe como fazer isso em Objective-C? Você já tentou reescrever o mesmo código em Swift?
Aaron Brager

Aqui está uma resposta realmente boa: stackoverflow.com/a/37992022/426571
el_quick

Respostas:


110

Vejo que você respondeu à pergunta um pouco, mas para fornecer uma maneira um pouco mais concisa, sem usar regex para responder à pergunta do título:

Para alterar a cor de um comprimento de texto, você precisa saber o índice inicial e final dos futuros caracteres coloridos na string, por exemplo

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

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

Em seguida, você converte em string atribuída e usa 'adicionar atributo' com NSForegroundColorAttributeName:

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

Uma lista de outros atributos padrão que você pode definir pode ser encontrada na documentação da Apple


20
NSColor é apenas OSX - use UIColor para IOS
Steve O'Connor

1
E se eu tiver var main_string = "Hello World Hello World Hello World" e precisar aplicar a cor em "World" em toda a string?
msmq de

main_string, string_to_colore rangenunca sofreram mutação. Considere alterá-los para letconstantes?
Cesare

Ótima solução. Você salvou meu dia.
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

e se a string for grande e tiver muitas palavras duplicadas (semelhantes). vai variar (de: ...) funciona?
Hatim

44

Atualização do 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.helpTexté uma UILabelsaída.


1
Oh Chris, você é meu herói. Estou procurando exatamente esse bloco de código há muito tempo.
Pan Mluvčí de

@chris. Quero mudar a string nsmutableattributed no textview, isso é possível
Uma Madhavi

é trabalho para uma única palavra. mas na minha string há várias palavras, é mudança de cor, mas depois escrevo depois dessa palavra de cor vermelha que a cor da palavra também é vermelha. então você pode dar qualquer solução, se tiver.
Dhaval Solanki de

Obrigado pela ajuda!
ssowri1

18

O Swift 4.2 e o Swift 5 colorem partes da corda.

Uma maneira muito fácil de usar NSMutableAttributedString ao estender a String. Isso também pode ser usado para colorir mais de uma palavra em toda a string.

Adicionar novo arquivo para extensões, Arquivo -> Novo -> Arquivo Swift com nome para ex. "NSAttributedString + TextColouring" e adicione o 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
    }
}

Agora você pode usar globalmente em qualquer viewcontroller que desejar:

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

myLabel.attributedText = attributedWithTextColor

Exemplo de uso de coloração de texto com swift 4


11

A resposta já foi dada em posts anteriores, mas eu tenho uma maneira diferente de fazer isso

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

Espero que isso ajude alguém!


@UmaMadhavi Qual é exatamente o seu requisito?
Anurag Sharma

Eu quero mudar o tamanho e a cor da fonte no textview. Estou recebendo em nsmutableattributedstring.
Uma Madhavi

@UmaMadhavi verifique este link1 e link2 . Pode ser útil!
Anurag Sharma

Falha se a fonte não estiver disponível.
SafeFastExpressive

10

A resposta de Chris foi uma grande ajuda para mim, então usei sua abordagem e me transformei em uma função que posso reutilizar. Isso me permite atribuir uma cor a uma substring, enquanto dou outra cor ao resto da string.

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
}

6

Swift 4.1

NSAttributedStringKey.foregroundColor

por exemplo, se você deseja alterar a fonte na NavBar:

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

6

Você pode usar esta extensão que eu testo

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

}

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

Recebo um erro quando faço isso. Eu acho que você quer isso sem .CGColor.
Bjorn Roche

@SarabjitSingh. como isso é possível para textview
Uma Madhavi

@UmaMadhavi ... Você só precisa adicionar self.textView.attributedText = myMutableString ..... Vai funcionar ...
Sarabjit Singh

4

A maneira mais fácil de rotular com estilos diferentes, como cor, fonte, etc., é usar a propriedade "Atributo" no Inspetor de atributos. Basta escolher parte do texto e alterá-lo como quiser

insira a descrição da imagem aqui


1
Supondo que você não está mudando as strings programaticamente
Alejandro Cumpa

4

Com base nas respostas antes de criar uma extensão de string

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

Você pode passar os atributos do texto para o método

Ligar assim

  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)

4

Swift 4.1

Eu mudei deste In Swift 3

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

E isso em Swift 4.0

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

para Swift 4.1

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

Funciona bem


Isso está mudando toda a string? Este é o mais legível para mim, mas existe uma maneira de alterar apenas palavras específicas dentro da string como o OP pediu.
Moondra de

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

2

Para todos que procuram " Aplicando uma cor específica a várias palavras no texto ", podemos fazer isso 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
    }
}

Link de referência: https://gist.github.com/aquajach/4d9398b95a748fd37e88


É possível usar seu código no aplicativo MacOS Cocoa? Tentei usá-lo em meu projeto de cacau, mas não há .attributedText no cacau NSTextView.
CaOs433

2

Isso pode funcionar para você

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

1
Embora este trecho de código possa ser a solução, incluir uma explicação realmente ajuda a melhorar a qualidade de sua postagem. Lembre-se de que você está respondendo à pergunta para leitores no futuro e essas pessoas podem não saber os motivos de sua sugestão de código.
HMD

2

Com esta função simples, você pode atribuir o texto e destacar a palavra escolhida.

Você também pode alterar o UITextView para 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
}

1

Para alterar a cor da fonte, primeiro selecione atribuída em vez de simples como na imagem abaixo

Em seguida, você precisa selecionar o texto no campo atribuído e, em seguida, selecionar o botão de cor no lado direito dos alinhamentos. Isso mudará a cor.


1

Você pode usar este método. Implementei esse método em minha classe de utilitário comum para acesso global.

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
}

0

Se você estiver usando Swift 3x e UITextView, talvez o NSForegroundColorAttributeName não funcione (não funcionou para mim, independentemente da abordagem que tentei).

Então, depois de pesquisar um pouco, encontrei uma solução.

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

0

Uma maneira super fácil de fazer isso.

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 obter mais detalhes, clique aqui: https://github.com/iOSTechHub/AttributedString


0

Você precisa alterar os parâmetros do textview, não os parâmetros da string atribuída

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

0

Verifique o cocoapod Prestyler :

Prestyler.defineRule("$", UIColor.orange)
label.attributedText = "This $text$ is orange".prestyled()

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


0

Você pode usar uma extensão simples

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)

  
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.