Swift'de NSMutableAttributedString kullanarak belirli bir metnin rengini değiştirme


100

Karşılaştığım sorun, bir TextView'daki belirli bir metnin textColor'unu değiştirebilmek istemem. Birleştirilmiş bir dize kullanıyorum ve yalnızca TextView metnine eklediğim dizeleri istiyorum. Görünüşe göre kullanmak istediğim şey NSMutableAttributedString, ancak bunu Swift'de nasıl kullanacağıma dair herhangi bir kaynak bulamıyorum. Şimdiye kadar sahip olduğum şey şuna benzer:

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

Buradan, textColor'larının değiştirilmesi gereken kelime aralığını bulmam ve bunları atıfta bulunulan dizeye eklemem gerektiğini biliyorum. Bilmem gereken şey, attributedString'den doğru dizeleri nasıl bulacağım ve sonra textColor'u nasıl değiştireceğim.

Çok düşük bir derecelendirmeye sahip olduğum için kendi sorumu cevaplayamıyorum, ama bulduğum cevap işte burada

Bazı kodların çevirisini yaparak kendi cevabımı buldum

NSAttributedString'de alt dizelerin özniteliklerini değiştirme

İşte Swift'deki uygulama örneği:

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

Birden çok Dizenin textColor'unu değiştirmek istediğim için, bunu işlemek için bir yardımcı işlev yapacağım, ancak bu, textColor'u değiştirmek için çalışır.


Bunu Objective-C'de nasıl yapacağınızı biliyor musunuz? Aynı kodu Swift'de yeniden yazmaya çalıştınız mı?
Aaron Brager

İşte gerçekten iyi bir cevap: stackoverflow.com/a/37992022/426571
el_quick

Yanıtlar:


110

Görüyorum ki soruyu bir şekilde yanıtlamışsınız, ancak başlık sorusunu yanıtlamak için normal ifade kullanmadan biraz daha kısa bir yol sağlamak için:

Bir metin uzunluğunun rengini değiştirmek için, dizedeki renkli olması gereken karakterlerin başlangıç ​​ve bitiş dizinini bilmeniz gerekir.

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

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

Ardından, ilişkilendirilmiş dizeye dönüştürür ve NSForegroundColorAttributeName ile "özellik ekle" yi kullanırsınız:

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

Ayarlayabileceğiniz diğer standart özniteliklerin bir listesi Apple'ın belgelerinde bulunabilir.


20
NSColor yalnızca OSX içindir - IOS için UIColor kullanın
Steve O'Connor

1
Ya var main_string = "Merhaba Dünya Merhaba Dünya Merhaba Dünya" varsa ve tüm dizede "Dünya" üzerine rengi uygulamam gerekirse ne olur?
msmq

main_string, string_to_colorVe rangemutasyona uğramış asla. Onları letsabit olarak değiştirmeyi düşünün ?
Cesare

Güzel çözüm. Günümü kurtardın.
Sagar Chauhan

107
let mainString = "Hello World"
let stringToColor = "World"

SWIFT 5

let range = (mainString as NSString).range(of: stringToColor)

let mutableAttributedString = NSMutableAttributedString.init(string: mainString)
mutableAttributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red, range: range)

textField = UITextField.init(frame: CGRect(x:10, y:20, width:100, height: 100))
textField.attributedText = mutableAttributedString

SWIFT 4.2

let range = (mainString as NSString).range(of: stringToColor)
    

let mutableAttributedString = NSMutableAttributedString.init(string: mainString)
mutableAttributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.red, range: range)     
    
textField = UITextField.init(frame: CGRect(x:10, y:20, width:100, height: 100))
textField.attributedText = mutableAttributedString

ya dize büyükse ve birçok yinelenen (benzer) kelime içeriyorsa. range (of: ...) çalışır mı?
Hatim

44

Swift 2.1 Güncellemesi:

 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.helpTextbir UILabelprizdir.


1
Oh Chris, sen benim kahramanımsın. Uzun zamandır bu tam kod bloğunu arıyorum.
Pan Mluvčí

@chris. Metin görünümünde nsmutable ilişkilendirilmiş dizeyi değiştirmek istiyorum, bu mümkün mü
Uma Madhavi

Tek kelime için çalışıyor ama benim dizimde birden fazla kelime var, renk değişiyor ama sonra o kırmızı renkli kelimeden sonra o kelimenin renginin de kırmızı olduğunu yazıyorum. eğer varsa herhangi bir çözüm verebilir misin?
Dhaval Solanki

Yardımın için teşekkürler!
ssowri1

19

Swift 4.2 ve Swift 5 , ipin parçalarını renklendirir.

String'i genişletirken NSMutableAttributedString'i kullanmanın çok kolay bir yolu. Bu aynı zamanda tüm dizede birden fazla kelimeyi renklendirmek için de kullanılabilir.

Uzantılar için yeni dosya ekleyin, Dosya -> Yeni -> Swift Dosyası, örn. "NSAttributedString + TextColouring" ve kodu ekleyin

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

Artık istediğiniz herhangi bir görüntü denetleyicide global olarak kullanabilirsiniz:

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

myLabel.attributedText = attributedWithTextColor

Swift 4 ile metin renklendirme kullanma örneği


11

Cevap önceki yazılarda zaten verilmiş ancak bunu yapmanın farklı bir yolu var

Hızlı 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

Umarım bu herkese yardımcı olur!


@UmaMadhavi Tam olarak ihtiyacın nedir?
Anurag Sharma

Metin görünümünde yazı tipi boyutunu ve yazı tipi rengini değiştirmek istiyorum. Bunu nsmutableattributedstring'de alıyorum.
Uma Madhavi

Bu kontrol @UmaMadhavi LINK1 ve LINK2 . Yararlı olabilir!
Anurag Sharma

Yazı tipi yoksa çöker.
SafeFastExpressive

10

Chris'in cevabı bana çok yardımcı oldu, bu yüzden yaklaşımını kullandım ve yeniden kullanabileceğim bir işe dönüştüm. Bu, dizenin geri kalanına başka bir renk verirken bir alt dizeye bir renk atayayım.

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

örneğin NavBar'da yazı tipini değiştirmek istiyorsanız:

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

6

Bu uzantıyı kullanabilirsin, üzerinde test ediyorum

hızlı 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

Bunu yaptığımda bir hata alıyorum. Sanırım bunu onsuz istiyorsun .CGColor.
Bjorn Roche

@SarabjitSingh. bu metin görünümü için nasıl mümkün olabilir
Uma Madhavi

@UmaMadhavi ... Sadece self.textView.attributedText = myMutableString eklemeniz gerekiyor ..... Çalışacak ...
Sarabjit Singh

4

Renk, yazı tipi vb. Gibi farklı stillerle etiket yapmanın en kolay yolu, Attributes Inspector'da "Attributed" özelliğini kullanmaktır. Metnin bir bölümünü seçin ve istediğiniz gibi değiştirin

görüntü açıklamasını buraya girin


1
Dizeleri programatik olarak değiştirmediğinizi varsayarsak
Alejandro Cumpa

4

Bir dize uzantısı oluşturmadan önceki cevaplara göre

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

Metnin niteliklerini yönteme aktarabilirsiniz.

Böyle ara

  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

Swift 3'te bundan değiştim

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

Ve bu Swift 4.0'da

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

için Swift 4.1

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

İyi çalışıyor


Bu tüm dizeyi mi değiştiriyor? Bu benim için en okunaklı olanıdır, ancak OP'nin istediği gibi dizedeki yalnızca belirli kelimeleri değiştirmenin bir yolu var mı?
Moondra

3

hızlı 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

" Metindeki birden çok kelimeye belirli bir renk uygulama " arayan herkes için bunu NSRegularExpression kullanarak yapabiliriz

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

Referans bağlantısı: https://gist.github.com/aquajach/4d9398b95a748fd37e88


Kodunuzu MacOS kakao uygulamasında kullanmak mümkün mü? Bunu kakao projemde kullanmayı denedim, ancak kakao NSTextView'da .attributedText yok.
CaOs433

2

Bu senin için işe yarayabilir

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
Bu kod parçacığı çözüm olabilir, ancak bir açıklama da dahil olmak üzere yayınınızın kalitesini artırmaya gerçekten yardımcı olur. Gelecekte okuyucular için soruyu yanıtladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceklerini unutmayın.
HMD

2

Bu basit işlevle metni atayabilir ve seçilen sözcüğü vurgulayabilirsiniz.

Ayrıca değiştirebilir UITextView için UILabel vb

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

Yazı tipi renginin rengini değiştirmek için, ilk önce aşağıdaki resimde olduğu gibi düz yerine ilişkilendirilmiş olanı seçin

Ardından, ilişkilendirilen alandaki metni seçmeniz ve ardından hizalamaların sağ tarafındaki renk düğmesini seçmeniz gerekir. Bu rengi değiştirecek.


1

Bu yöntemi kullanabilirsiniz. Bu yöntemi genel olarak erişim sağlamak için ortak yardımcı sınıfımda uyguladım.

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 ve UITextView kullanıyorsanız, NSForegroundColorAttributeName işe yaramayabilir (hangi yaklaşımı denediğim önemli değil).

Bu yüzden, biraz araştırma yaptıktan sonra bir çözüm buldum.

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

Bunu yapmanın süper kolay yolu.

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

Daha fazla ayrıntı için buraya tıklayın: https://github.com/iOSTechHub/AttributedString


0

Öznitelikli dizenin parametrelerini değil, metin görünümü parametrelerini değiştirmeniz gerekir

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

0

Lütfen cocoapod Prestyler'ı kontrol edin :

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
}

}

EmailLbl.attributedText = EmailLbl.text! .markAsMandatoryField () kullanın


0

Basit bir uzantı olarak kullanabilirsiniz

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)

  
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.