问题
I want to change the text color of a specific text within a UITextView which matches an index of an array. I was able to slightly modify this answer but unfortunatly the text color of each matching phrase is only changed once.
var chordsArray = ["Cmaj", "Bbmaj7"]
func getColoredText(textView: UITextView) -> NSMutableAttributedString {
let text = textView.text
let string:NSMutableAttributedString = NSMutableAttributedString(string: text)
let words:[String] = text.componentsSeparatedByString(" ")
for word in words {
if (chordsArray.contains(word)) {
let range:NSRange = (string.string as NSString).rangeOfString(word)
string.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)
}
}
chords.attributedText = string
return string
}
Outcome
回答1:
Sorry, I just noticed your message. Here is a working example (tested in a playground):
import UIKit
func apply (string: NSMutableAttributedString, word: String) -> NSMutableAttributedString {
let range = (string.string as NSString).rangeOfString(word)
return apply(string, word: word, range: range, last: range)
}
func apply (string: NSMutableAttributedString, word: String, range: NSRange, last: NSRange) -> NSMutableAttributedString {
if range.location != NSNotFound {
string.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)
let start = last.location + last.length
let end = string.string.characters.count - start
let stringRange = NSRange(location: start, length: end)
let newRange = (string.string as NSString).rangeOfString(word, options: [], range: stringRange)
apply(string, word: word, range: newRange, last: range)
}
return string
}
var chordsArray = ["Cmaj", "Bbmaj7"]
var text = "Cmaj Bbmaj7 I Love Swift Cmaj Bbmaj7 Swift"
var newText = NSMutableAttributedString(string: text)
for word in chordsArray {
newText = apply(newText, word: word)
}
newText
回答2:
In case, someone needs it in swift 4. This is what I get from my Xcode 9 playground :).
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController
{
override func loadView()
{
let view = UIView()
view.backgroundColor = .white
let textView = UITextView()
textView.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
textView.text = "@Kam @Jam @Tam @Ham"
textView.textColor = .black
view.addSubview(textView)
self.view = view
let query = "@"
if let str = textView.text {
let text = NSMutableAttributedString(string: str)
var searchRange = str.startIndex..<str.endIndex
while let range = str.range(of: query, options: NSString.CompareOptions.caseInsensitive, range: searchRange) {
text.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.gray, range: NSRange(range, in: str))
searchRange = range.upperBound..<searchRange.upperBound
}
textView.attributedText = text
}
}
}
PlaygroundPage.current.liveView = MyViewController()
I think for swift 3, you need to convert Range(String.Index) to NSRange manually like this.
let start = str.distance(from: str.startIndex, to: range.lowerBound)
let len = str.distance(from: range.lowerBound, to: range.upperBound)
let nsrange = NSMakeRange(start, len)
text.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.gray, range: nsrange)
回答3:
Swift 4.2 and 5
let string = "* Your receipt photo was not clear or did not capture the entire receipt details. See our tips here.\n* Your receipt is not from an eligible grocery, convenience or club store."
let attributedString = NSMutableAttributedString.init(string: string)
let range = (string as NSString).range(of: "See our tips")
attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.blue, range: range)
txtView.attributedText = attributedString
txtView.isUserInteractionEnabled = true
txtView.isEditable = false
Output
来源:https://stackoverflow.com/questions/33472171/uitextview-change-text-color-of-specific-text