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.


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


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

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.


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


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!


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

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]

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

}

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

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


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)

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


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

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


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

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
}

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.


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
}

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

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


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
    ]

0

Proszę sprawdzić 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
}

}

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


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)

  
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.