Zmiana koloru określonego tekstu za pomocą NSMutableAttributedString w Swift

100

Problem, który mam, polega na tym, że chcę mieć możliwość zmiany textColor określonego tekstu w TextView. Używam połączonego ciągu i chcę tylko ciągów, które dołączam do tekstu TextView. Wygląda na to, że chcę użyć NSMutableAttributedString, ale nie znajduję żadnych zasobów, jak to wykorzystać w Swift. Do tej pory mam coś takiego:

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

Stąd wiem, że muszę znaleźć zakres słów, które wymagają zmiany ich textColor, a następnie dodać je do przypisanego ciągu. Muszę wiedzieć, jak znaleźć prawidłowe ciągi z atrybutu attributeString, a następnie zmienić ich textColor.

Ponieważ mam zbyt niską ocenę, nie mogę odpowiedzieć na własne pytanie, ale oto odpowiedź, którą znalazłem

Znalazłem własną odpowiedź, tłumacząc z tłumaczenia jakiegoś kodu z

Zmień atrybuty podciągów w NSAttributedString

Oto przykład implementacji w 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

Ponieważ chcę zmienić textColor wielu ciągów, utworzę funkcję pomocniczą, aby to obsłużyć, ale to działa w przypadku zmiany textColor.

richyrich24
źródło
Czy wiesz, jak to zrobić w Objective-C? Czy próbowałeś przepisać ten sam kod w języku Swift?
Aaron Brager
Oto naprawdę dobra odpowiedź: stackoverflow.com/a/37992022/426571
el_quick

Odpowiedzi:

110

Widzę, że nieco odpowiedziałeś na pytanie, ale aby podać nieco bardziej zwięzły sposób bez użycia wyrażenia regularnego do odpowiedzi na pytanie tytułowe:

Aby zmienić kolor długości tekstu, musisz znać indeks początkowy i końcowy kolorowych znaków w ciągu np.

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

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

Następnie konwertujesz na przypisany ciąg i używasz `` dodaj atrybut '' z NSForegroundColorAttributeName:

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

Lista dalszych standardowych atrybutów, które możesz ustawić, znajduje się w dokumentacji Apple

james_alvarez
źródło
20
NSColor to tylko OSX - używaj UIColor dla IOS
Steve O'Connor,
1
A jeśli mam var main_string = "Hello World Hello World Hello World" i muszę nałożyć kolor na "World" w całym ciągu?
msmq,
main_string, string_to_colori rangenigdy nie zostały zmutowane. Rozważ zmianę ich na letstałe?
Cesare
Niezłe rozwiązanie. Uratowałeś mój dzień.
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
źródło
co jeśli ciąg jest duży i zawiera wiele zduplikowanych (podobnych) słów. będzie zakres (z: ...) działa?
Hatim
44

Aktualizacja 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.helpTextjest UILabelgniazdem.

Chris
źródło
1
Och Chris, jesteś moim bohaterem. Długo szukam tego dokładnie bloku kodu.
Pan Mluvčí
@chris. Chcę zmienić ciąg nsmutableattributed w widoku tekstowym, czy to możliwe
Uma Madhavi
to działa dla pojedynczego słowa. ale w moim ciągu jest wiele słów, które zmieniają kolor, ale potem piszę po tym czerwonym kolorze, że kolor słowa jest również czerwony. więc czy możesz podać jakieś rozwiązanie, jeśli masz.
Dhaval Solanki
Dziękuję za pomoc!
ssowri1
18

Swift 4.2 i Swift 5 kolorują części sznurka.

Bardzo łatwy sposób użycia NSMutableAttributedString podczas rozszerzania String. Można to również użyć do kolorowania więcej niż jednego słowa w całym ciągu.

Dodaj nowy plik do rozszerzeń, Plik -> Nowy -> Swift Plik o nazwie np. „NSAttributedString + TextColouring” i dodaj kod

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

Teraz możesz używać globalnie w dowolnym kontrolerze widoku:

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

myLabel.attributedText = attributedWithTextColor

Przykład użycia kolorowania tekstu w Swift 4

Doci
źródło
11

Odpowiedź została już udzielona w poprzednich postach, ale mam inny sposób na zrobienie tego

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

Mam nadzieję, że to pomoże każdemu!

Anurag Sharma
źródło
@UmaMadhavi Jakie są Twoje wymagania?
Anurag Sharma
Chcę zmienić rozmiar i kolor czcionki w widoku tekstu. Otrzymuję to w nsmutableattributedstring.
Uma Madhavi
@UmaMadhavi sprawdź ten link1 i link2 . To może być pomocne!
Anurag Sharma
Awaria, jeśli czcionka jest niedostępna.
SafeFastExpressive
10

Odpowiedź Chrisa bardzo mi pomogła, więc zastosowałem jego podejście i zmieniłem go w funkcję, której mogę użyć ponownie. To pozwoli mi przypisać kolor do podciągu, jednocześnie nadając reszcie łańcucha inny kolor.

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
źródło
6

Swift 4.1

NSAttributedStringKey.foregroundColor

na przykład, jeśli chcesz zmienić czcionkę w NavBar:

self.navigationController?.navigationBar.titleTextAttributes = [ NSAttributedStringKey.font: UIFont.systemFont(ofSize: 22), NSAttributedStringKey.foregroundColor: UIColor.white]
swift2geek
źródło
6

Możesz użyć tego rozszerzenia, które przetestuję

szybki 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 Angry
źródło
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
źródło
Gdy to robię, pojawia się błąd. Myślę, że chcesz tego bez .CGColor.
Bjorn Roche
@SarabjitSingh. jak to możliwe w przypadku widoku tekstowego
Uma Madhavi
@UmaMadhavi ... Wystarczy dodać self.textView.attributedText = myMutableString ..... Będzie działać ...
Sarabjit Singh
4

Najłatwiejszym sposobem na utworzenie etykiety z innym stylem, takim jak kolor, czcionka itp., Jest użycie właściwości „Attributed” w Inspektorze atrybutów. Po prostu wybierz fragment tekstu i zmień go tak, jak chcesz

wprowadź opis obrazu tutaj

jMelvins
źródło
1
Przypuśćmy, że nie zmieniasz strun programowo
Alejandro Cumpa,
4

Na podstawie odpowiedzi, zanim utworzyłem rozszerzenie ciągu

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

Możesz przekazać atrybuty tekstu do metody

Zadzwoń tak

  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
źródło
4

Swift 4.1

Zmieniłem się z tego w Swift 3

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

I to w Swift 4.0

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

do Swift 4.1

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

Działa w porządku

niravdesai21
źródło
Czy to zmienia cały ciąg? Jest to dla mnie najbardziej czytelne, ale czy istnieje sposób na zmianę tylko określonych słów w ciągu, tak jak poprosił OP.
Moondra
3

szybki 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
źródło
2

Dla wszystkich, którzy szukają opcji „ Stosowanie określonego koloru do wielu słów w tekście ”, możemy to zrobić za pomocą 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 referencyjny: https://gist.github.com/aquajach/4d9398b95a748fd37e88

cgeek
źródło
Czy można użyć kodu w aplikacji MacOS cocoa? Próbowałem go użyć w moim projekcie cocoa, ale nie ma .attributedText w kakaowym NSTextView.
CaOs433
2

To może zadziałać dla Ciebie

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
źródło
1
Chociaż ten fragment kodu może być rozwiązaniem, dołączenie wyjaśnienia naprawdę pomaga poprawić jakość Twojego posta. Pamiętaj, że odpowiadasz na pytanie do czytelników w przyszłości, a osoby te mogą nie znać powodów, dla których zaproponowałeś kod.
HMD
2

Dzięki tej prostej funkcji możesz przypisać tekst i zaznaczyć wybrane słowo.

Możesz także zmienić UITextView na UILabel itp.

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
}
Dan Developer
źródło
1

Aby zmienić kolor czcionki, najpierw wybierz atrybut przypisany zamiast zwykłego, jak na poniższym obrazku

Następnie musisz zaznaczyć tekst w przypisanym polu, a następnie wybrać kolorowy przycisk po prawej stronie linii trasowania. To zmieni kolor.

Kingsley Mitchell
źródło
1

Możesz użyć tej metody. Zaimplementowałem tę metodę w mojej wspólnej klasie narzędziowej, aby uzyskać dostęp globalny.

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
źródło
0

Jeśli używasz Swift 3x i UITextView, być może NSForegroundColorAttributeName nie zadziała (nie zadziałało dla mnie bez względu na podejście, które wypróbowałem).

Tak więc, po pewnym kopaniu, znalazłem rozwiązanie.

//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
źródło
0

Super łatwy sposób na zrobienie tego.

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

Aby uzyskać więcej informacji, kliknij tutaj: https://github.com/iOSTechHub/AttributedString

Ashish Chauhan
źródło
0

Musisz zmienić parametry widoku tekstu, a nie parametry przypisanego ciągu

textView.linkTextAttributes = [
        NSAttributedString.Key.foregroundColor: UIColor.red,
        NSAttributedString.Key.underlineColor: UIColor.red,
        NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue
    ]
Maxvale
źródło
0

Proszę sprawdzić cocoapod Prestyler :

Prestyler.defineRule("$", UIColor.orange)
label.attributedText = "This $text$ is orange".prestyled()
Kruiller
źródło
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
}

}

użyj EmailLbl.attributedText = EmailLbl.text! .markAsMandatoryField ()

NSurajit
źródło
0

Możesz użyć jako prostego rozszerzenia

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
źródło