Зміна конкретного кольору тексту за допомогою NSMutableAttributedString у Swift


100

Проблема, яка у мене виникає, полягає в тому, що я хочу мати змогу змінити textColor певного тексту в TextView. Я використовую об'єднаний рядок і просто хочу, щоб рядки, які я додаю до тексту TextView, просто хочу. Здається, що я хочу використовувати NSMutableAttributedString, але я не знаходжу жодних ресурсів, як це використовувати в Swift. Що у мене поки що є щось подібне:

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

Звідси я знаю, що мені потрібно знайти діапазон слів, які потребують змінити їх текстColor, а потім додати їх до атрибутивного рядка. Що мені потрібно знати, як знайти правильні рядки з attributedString, а потім змінити їх textColor.

Оскільки у мене занадто низький рейтинг, я не можу відповісти на власне запитання, але ось відповідь, яку я знайшов

Я знайшов власну відповідь, перекладаючи з перекладу якогось коду з

Зміна атрибутів підрядів у NSAttributedString

Ось приклад реалізації в 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

Оскільки я хочу змінити textColor з декількох рядків, я зроблю допоміжну функцію для вирішення цього питання, але це працює для зміни textColor.


Чи знаєте ви, як це зробити в Objective-C? Ви намагалися переписати той самий код у Swift?
Аарон Брагер

Ось дуже хороший відповідь: stackoverflow.com/a/37992022/426571
el_quick

Відповіді:


110

Я бачу, що ви відповіли на питання дещо, але надати трохи більш стислий спосіб, не використовуючи регулярний вираз для відповіді на заголовкове запитання:

Щоб змінити колір довжини тексту, вам потрібно знати початковий та кінцевий індекси кольорових символів у рядку, наприклад

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

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

Потім ви перетворюєте в атрибутивний рядок і використовуєте 'add attribute' за допомогою NSForegroundColorAttributeName:

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

Список додаткових стандартних атрибутів, які ви можете встановити, ви можете знайти в документації Apple


20
NSColor - це лише OSX - використовуйте UIColor для IOS
Стів О'Коннор

1
Що робити, якщо у мене var main_string = "Hello World Hello World Hello World", і мені потрібно застосувати колір у "World" цілим рядком?
msmq

main_string, string_to_colorі rangeніколи не змінювались. Подумаєте змінити їх на letпостійні?
Чезаре

Приємне рішення. Ти врятував мій день.
Сагар Чаухан

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

що робити, якщо рядок великий і містить багато дублюваних (подібних) слів. буде діапазон (з: ...) працює?
Хатим

44

Оновлення 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є UILabelрозеткою.


1
О, Кріс, ти мій герой. Я давно шукаю саме цей блок коду.
Пан Млувчі

@chris. Я хочу змінити nsmutableпоширений рядок у перегляді тексту, чи можливо це
Uma Madhavi

це робота для одного word.but у моєму рядку є кілька слів це зміна кольору, але потім я пишу після цього слова червоного кольору, що слово слова також є червоним. Так що ви можете дати рішення, якщо у вас є.
Дхаваль Соланкі

Дякую за твою допомогу!
ssowri1

18

Swift 4.2 та Swift 5 колоризують частини струни.

Дуже простий спосіб використання NSMutableAttributedString під час розширення String. Це також можна використовувати для розфарбовування більше одного слова в цілому рядку.

Додайте новий файл для розширень, Файл -> Новий -> Швидкий файл із назвою для колишнього. "NSAttributedString + TextColouring" і додайте код

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

Тепер ви можете використовувати глобально будь-який програму перегляду:

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

myLabel.attributedText = attributedWithTextColor

Приклад використання розмальовки тексту за допомогою швидкого 4


11

Відповідь вже дано в попередніх публікаціях, але я маю інший спосіб зробити це

Швидкий 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

Сподіваюся, це допомагає комусь!


@UmaMadhavi Яка ваша вимога саме?
Анураг Шарма

Я хочу змінити розмір шрифту та колір шрифту в текстовому перегляді. Я отримую це в nsmutableattributedstring.
Ума Мадхаві

@UmaMadhavi перевірити цю LINK1 і LINK2 . Це може бути корисно!
Анураг Шарма

Збій, якщо шрифт недоступний.
SafeFastExpressive

10

Відповідь Кріса мені дуже допомогла, тому я застосував його підхід і перетворився на функцію, яку я можу використовувати повторно. Це дозволить мені призначити колір підрядку, а решті рядка надати інший колір.

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

Швидкий 4.1

NSAttributedStringKey.foregroundColor

наприклад, якщо ви хочете змінити шрифт у NavBar:

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

6

Ви можете використовувати це розширення

стрімкий 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

Швидкий 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

Я отримую помилку, коли це роблю. Я думаю, ти хочеш цього без .CGColor.
Бьорн Рош

@SarabjitSingh. як це можливо для перегляду тексту
Ума Мадхаві

@UmaMadhavi ... Вам просто потрібно додати self.textView.attributedText = myMutableString ..... Це спрацює ...
Sarabjit Singh

4

Найпростіший спосіб зробити мітку з різним стилем, наприклад кольором, шрифтом тощо, - це використовувати властивість "Attributed" в Attributes Inspector. Просто виберіть частину тексту та змініть її так, як вам хочеться

введіть тут опис зображення


1
Припустимо, що ви не змінюєте рядки програмно
Алехандро Кумпа

4

На основі відповідей, перш ніж я створив розширення рядка

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

Можна передати атрибути тексту тексту методу

Телефонуйте так

  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

Швидкий 4.1

Я змінився з цього в Swift 3

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

І це у Swift 4.0

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

до Swift 4.1

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

Добре працює


Це змінює весь рядок? Це найбільш читабельно для мене, але чи є спосіб змінити лише певні слова в рядку, як запитується ОП.
Мондра

3

стрімкий 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

Для всіх, хто шукає " Застосування певного кольору до кількох слів у тексті ", ми можемо це зробити за допомогою 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
    }
}

Посилання на посилання: https://gist.github.com/aquajach/4d9398b95a748fd37e88


Чи можливо використовувати свій код у додатку для какао MacOS? Я намагався використовувати його в своєму проекті з какао, але в какао NSTextView немає .attributedText.
CaOs433

2

Це може бути для вас справою

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
Хоча цей фрагмент коду може бути вирішенням, включаючи пояснення, справді допомагає покращити якість вашої публікації. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду.
HMD

2

За допомогою цієї простої функції ви можете призначити текст і виділити вибране слово.

Ви також можете змінити UITextView на UILabel тощо.

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

Щоб змінити колір кольору шрифту, спочатку виберіть атрибут, а не простий, як на зображенні нижче

Потім потрібно вибрати текст у полі, що приписується, а потім вибрати кольорову кнопку в правій частині вирівнювання. Це змінить колір.


1

Можна використовувати цей метод. Я реалізував цей метод у своєму загальному утилітному класі, щоб отримати доступ у глобальному масштабі.

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

Якщо ви використовуєте Swift 3x та UITextView, можливо, NSForegroundColorAttributeName не буде працювати (це не спрацювало для мене незалежно від того, який підхід я намагався).

Отже, після деякого копання навколо я знайшов рішення.

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

Супер простий спосіб зробити це.

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

Детальніше натисніть тут: https://github.com/iOSTechHub/AttributedString


0

Вам потрібно змінити параметри перегляду тексту, а не параметри атрибутивного рядка

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


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
}

}

використовувати EmailLbl.attributedText = EmailLbl.text! .markAsMandatoryField ()


0

Ви можете використовувати як просте розширення

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)

  
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.