การเปลี่ยนสีของข้อความโดยใช้ NSMutableAttributedString ใน Swift


103

ปัญหาที่ฉันพบคือฉันต้องการเปลี่ยน textColor ของข้อความบางข้อความใน TextView ฉันใช้สตริงที่ต่อกันและต้องการเพียงแค่สตริงที่ฉันต่อท้ายข้อความของ TextView ดูเหมือนว่าสิ่งที่ฉันต้องการใช้คือNSMutableAttributedStringแต่ฉันไม่พบแหล่งข้อมูลใด ๆ เกี่ยวกับวิธีใช้สิ่งนี้ใน Swift สิ่งที่ฉันมีจนถึงตอนนี้คือ:

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

จากที่นี่ฉันรู้ว่าฉันต้องหาช่วงของคำที่ต้องมีการเปลี่ยนแปลง textColor แล้วเพิ่มลงในสตริงที่มาจากแหล่ง สิ่งที่ฉันต้องรู้คือวิธีค้นหาสตริงที่ถูกต้องจาก 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 หรือไม่?
Aaron Brager

นี่คือคำตอบที่ดีจริงๆ: stackoverflow.com/a/37992022/426571
el_quick

คำตอบ:


112
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

จะเกิดอะไรขึ้นถ้าสตริงมีขนาดใหญ่และมีคำที่ซ้ำกัน (คล้ายกัน) จำนวนมาก range (of: ... ) จะใช้ได้หรือไม่
Hatim

110

ฉันเห็นว่าคุณตอบคำถามไปบ้างแล้ว แต่เพื่อให้กระชับขึ้นเล็กน้อยโดยไม่ต้องใช้ regex เพื่อตอบคำถามชื่อเรื่อง:

ในการเปลี่ยนสีของความยาวของข้อความคุณจำเป็นต้องทราบดัชนีเริ่มต้นและจุดสิ้นสุดของอักขระที่เป็นสีในสตริงเช่น

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

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

จากนั้นคุณแปลงเป็นสตริงที่มีการระบุแหล่งที่มาและใช้ 'เพิ่มแอตทริบิวต์' กับ NSForegroundColorAttributeName

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

รายการคุณสมบัติมาตรฐานเพิ่มเติมที่คุณสามารถตั้งได้มีอยู่ในเอกสารของ Apple


20
NSColor เป็น OSX เท่านั้น - ใช้ UIColor สำหรับ IOS
Steve O'Connor

1
จะเกิดอะไรขึ้นถ้าฉันมี var main_string = "Hello World Hello World Hello World" และฉันต้องใช้สีกับ "World" ทั้งสตริง?
msmq

main_string, string_to_colorและrangeไม่เคยถูกกลายพันธุ์ พิจารณาเปลี่ยนเป็นletค่าคงที่หรือไม่?
Cesare

ทางออกที่ดี คุณได้บันทึกวันของฉัน
Sagar Chauhan

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
โอ้คริสคุณเป็นฮีโร่ของฉัน ฉันกำลังค้นหาบล็อกรหัสนี้เป็นเวลานาน
Pan Mluvčí

@ คริส. ฉันต้องการเปลี่ยนสตริง nsmutableattributed ใน textview เป็นไปได้หรือไม่
Uma Madhavi

มันใช้งานได้กับคำเดียว แต่ในสตริงของฉันมีหลายคำมันเปลี่ยนสี แต่ฉันก็เขียนหลังจากคำสีแดงนั้นสีของคำนั้นก็เป็นสีแดงด้วยดังนั้นคุณสามารถให้วิธีแก้ปัญหาใด ๆ ได้หากคุณมี
Dhaval Solanki

ขอขอบคุณสำหรับความช่วยเหลือของคุณ!
ssowri1

21

Swift 4.2และSwift 5 ทำให้ส่วนของสตริงเป็นสี

วิธีที่ง่ายมากในการใช้ NSMutableAttributedString ในขณะที่ขยาย String นอกจากนี้ยังสามารถใช้เพื่อระบายสีมากกว่าหนึ่งคำในสตริงทั้งหมด

เพิ่มไฟล์ใหม่สำหรับนามสกุลไฟล์ -> ใหม่ -> ไฟล์ Swift พร้อมชื่อเช่น "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

มีคำตอบอยู่แล้วในโพสต์ก่อนหน้านี้ แต่ฉันมีวิธีอื่นในการทำเช่นนี้

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

หวังว่านี่จะช่วยทุกคน!


@UmaMadhavi ความต้องการของคุณคืออะไร?
Anurag Sharma

ฉันต้องการเปลี่ยนขนาดตัวอักษรและสีแบบอักษรใน textview ฉันได้รับมันใน nsmutableattributedstring
Uma Madhavi

@UmaMadhavi ตรวจสอบนี้link1และlink2 อาจเป็นประโยชน์!
Anurag Sharma

เกิดปัญหาหากไม่มีแบบอักษร
SafeFastExpressive

10

คำตอบของคริสช่วยฉันได้มากดังนั้นฉันจึงใช้แนวทางของเขาและกลายเป็น func ที่ฉันสามารถนำกลับมาใช้ได้ ฉันขอกำหนดสีให้กับสตริงย่อยในขณะที่ให้ส่วนที่เหลือของสตริงเป็นสีอื่น

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
}

7

Swift 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

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

ฉันได้รับข้อผิดพลาดเมื่อฉันทำสิ่งนี้ .CGColorฉันคิดว่าคุณอยากให้เรื่องนี้ได้โดยไม่ต้อง
Bjorn Roche

@SarabjitSingh. จะเป็นไปได้อย่างไรสำหรับ textview
Uma Madhavi

@UmaMadhavi ... คุณแค่ต้องเพิ่ม self.textView.attributedText = myMutableString ..... มันจะได้ผล ...
Sarabjit Singh

4

วิธีที่ง่ายที่สุดในการทำป้ายกำกับที่มีสไตล์แตกต่างกันเช่นสีแบบอักษรเป็นต้นคือใช้คุณสมบัติ "ระบุแหล่งที่มา" ในตัวตรวจสอบแอตทริบิวต์ เพียงเลือกบางส่วนของข้อความและเปลี่ยนตามที่คุณต้องการ

ป้อนคำอธิบายภาพที่นี่


1
อ้างว่าคุณไม่ได้เปลี่ยนสตริงโดยทางโปรแกรม
Alejandro Cumpa

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

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

ใช้งานได้ดี


นี่คือการเปลี่ยนสตริงทั้งหมด? นี่เป็นคำที่อ่านง่ายที่สุดสำหรับฉัน แต่มีวิธีเปลี่ยนเฉพาะคำเฉพาะภายในสตริงเช่นที่ OP ถามหรือไม่
Moondra

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 ฉันพยายามใช้มันในโครงการโกโก้ของฉัน แต่ไม่มี .attributedText ในโกโก้ NSTextView
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

วิธีทำที่ง่ายสุด ๆ

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


ยอดเยี่ยมขอบคุณ หลังจากใช้คลาสที่อ้างอิงจากลิงค์บน GitHub สิ่งนี้ได้รับสิ่งที่ฉันกำลังมองหา
Dominick

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
}

1

คุณสามารถใช้เป็นนามสกุลธรรมดา

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)

  

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

คุณต้องเปลี่ยนพารามิเตอร์ textview ไม่ใช่พารามิเตอร์ของสตริงที่ประกอบ

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.