UITextView和UITextField中是否可以更改单个词的颜色?

33

在UITextView和UITextField中,是否可以改变单词的颜色?

如果我输入了一个带符号前缀的单词(例如:@word),它的颜色能被更改吗?


3
NSAttributedString是苹果公司的一种字符串类,用于在iOS和macOS应用程序中展示富文本。它允许您对字符串进行格式化,例如字体、颜色、段落样式等,并且可以将这些属性应用于不同的范围内。使用NSAttributedString,您可以创建具有不同样式和格式的文本。例如,在一个标签中,您可以在文本的一部分使用一种字体,而在另一部分使用另一种字体,或者更改文本的背景颜色等。它在文本编辑器、聊天应用程序、邮件应用程序等方面很有用。 - iDev
9个回答

67

是的,你需要使用NSAttributedString来实现,可以在此处找到示例代码。

扫描单词并找到其范围,然后更改颜色。

编辑:

- (IBAction)colorWord:(id)sender {
    NSMutableAttributedString * string = [[NSMutableAttributedString alloc]initWithString:self.text.text];

    NSArray *words=[self.text.text componentsSeparatedByString:@" "];

    for (NSString *word in words) {        
        if ([word hasPrefix:@"@"]) {
            NSRange range=[self.text.text rangeOfString:word];
            [string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];           
        }
    }
    [self.text setAttributedText:string];
}

编辑2:请查看截图enter image description here


1
但如何将TextField中的特定单词存储为字符串呢? - Nithin M Keloth
@AnoopVaidya 这个解决方案是错误的,因为它只影响每个单词的第一次出现。 - pkacprzak
我有一个疑问,我们不能隐藏“@word”中的“@”吗? - Mounika
嗨@Mounika:是的,你可以。但根据所问的问题,我以上面的答案回答了。对于你的问题,你可以在上述代码后用@""替换@"@"以更改颜色。这不是很简单吗? - Anoop Vaidya
@AnoopVaidya 谢谢,我已经修复了 :) - Mounika
显示剩余17条评论

6
这是根据@Anoop Vaidya的答案编写的一种Swift实现。此函数检测“{|myword|}”之间的任何单词,并将这些单词标为红色并删除特殊字符。希望这能帮助其他人:
 func getColoredText(text:String) -> NSMutableAttributedString{
    var string:NSMutableAttributedString = NSMutableAttributedString(string: text)
    var words:[NSString] = text.componentsSeparatedByString(" ")

    for (var word:NSString) in words {
        if (word.hasPrefix("{|") && word.hasSuffix("|}")) {
            var range:NSRange = (string.string as NSString).rangeOfString(word)
            string.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)
            word = word.stringByReplacingOccurrencesOfString("{|", withString: "")
            word = word.stringByReplacingOccurrencesOfString("|}", withString: "")
            string.replaceCharactersInRange(range, withString: word)
        }
    }
    return string
}

您可以像这样使用它:
self.msgText.attributedText = self.getColoredText("i {|love|} this!")

@Philip,你能解释一下你得到了什么吗? - Fareed Alnamrouti

5

在 @fareed 的答案基础上进行了修改,适用于Swift 2.0,并已经测试通过(在Playground中测试):

func getColoredText(text: String) -> NSMutableAttributedString {
    let string:NSMutableAttributedString = NSMutableAttributedString(string: text)
    let words:[String] = text.componentsSeparatedByString(" ")
    var w = ""

    for word in words {
        if (word.hasPrefix("{|") && word.hasSuffix("|}")) {
            let range:NSRange = (string.string as NSString).rangeOfString(word)
            string.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)
            w = word.stringByReplacingOccurrencesOfString("{|", withString: "")
            w = w.stringByReplacingOccurrencesOfString("|}", withString: "")
            string.replaceCharactersInRange(range, withString: w)
        }
    }
    return string
}

getColoredText("i {|love|} this!")

嗨,我正在尝试稍微修改这个程序以便它能够处理一个字符串数组,但目前遇到了一些困难,不知道你是否能帮助我解决?我在这里提出了问题。 - kye

4

@fareed namrouti 的实现已经重写为 Swift 3。

func getColoredText(text: String) -> NSMutableAttributedString {
    let string:NSMutableAttributedString = NSMutableAttributedString(string: text)
    let words:[String] = text.components(separatedBy:" ")
    var w = ""

    for word in words {
        if (word.hasPrefix("{|") && word.hasSuffix("|}")) {
            let range:NSRange = (string.string as NSString).range(of: word)
            string.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: range)
            w = word.replacingOccurrences(of: "{|", with: "")
            w = w.replacingOccurrences(of:"|}", with: "")
            string.replaceCharacters(in: range, with: w)
        }
    }
    return string
}

1
-(void)colorHashtag
{
NSMutableAttributedString * string = [[NSMutableAttributedString alloc]initWithString:textView.text];

NSString *str = textView.text;
NSError *error = nil;

//I Use regex to detect the pattern I want to change color
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"#(\\w+)" options:0 error:&error];



NSArray *matches = [regex matchesInString:textView.text options:0 range:NSMakeRange(0, textView.text.length)];

for (NSTextCheckingResult *match in matches) {
    NSRange wordRange = [match rangeAtIndex:0];
    [string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:wordRange]; 
}

[textView setAttributedText:string];
}

0
为了阐述Jamal Kharrat的答案,并将其重写为SWIFT,以下是在UITextView中执行此操作的方法:
  1. 在Storyboard中将UITextView设置为“Attributed”
  2. 右键单击并拖动到视图顶部的ViewController图标(XC 6),然后设置委托
  3. 为您的UITextView创建IBOutlet(我们将其称为“textView”)
  4. 使您的类符合UITextViewDelegate
以下是Jamal在SWIFT中编写的函数:
func colorHastag(){
    var string:NSMutableAttributedString = NSMutableAttributedString(string: textView.text)
    var str:NSString = textView.text
    var error:NSError?
    var match:NSTextCheckingResult?

    var regEx:NSRegularExpression = NSRegularExpression(pattern: "#(\\w+)", options: nil, error: &error)!
    var matches:NSArray = regEx.matchesInString(textView.text, options: nil, range: NSMakeRange(0, countElements(textView.text)))

    for (match) in matches {
        var wordRange:NSRange = match.rangeAtIndex(0)
        string.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor(), range: wordRange)
    }

    textView.attributedText = string
}

现在,您需要调用此函数。为了在用户每次键入字符时执行此操作,您可以使用:

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    self.colorHastag()
    return true
}

你会注意到我将颜色改为了蓝色。你可以将其设置为任何颜色。此外,你可以去掉每个变量的 :Type。你还需要设置 becomeFirstResponder() 并处理 resignFirstResponder() 以提供良好的用户体验。你也可以加入一些错误处理。这只会将哈希标签转换为蓝色。你需要修改或添加一个正则表达式来处理 @ 符号。

当单词中包含特殊字符时,它将会出现错误。 - kalpesh

0

解决方案如下:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];

NSArray *words=[txtDescription.text componentsSeparatedByString:@" "];

for (NSString *word in words)
{
    if ([word hasPrefix:@"@"] || [word hasPrefix:@"#"])
    {
        [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ ", word]
                                                                                 attributes:@{NSFontAttributeName: [UIFont fontWithName:FONT_LIGHT size:15],
                                                                                              NSForegroundColorAttributeName: [ImageToolbox colorWithHexString:@"f64d5a"]}]];
    }
    else // normal text
    {
        [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ ", word]
                                                                                 attributes:@{NSFontAttributeName: [UIFont fontWithName:FONT_LIGHT size:15],
                                                                                              NSForegroundColorAttributeName: [ImageToolbox colorWithHexString:@"3C2023"]}]];
    }
}

if([[attributedString string] hasSuffix:@" "]) // loose the last space
{
    NSRange lastCharRange;
    lastCharRange.location=0;
    lastCharRange.length=[attributedString string].length-1;

    attributedString=[[NSMutableAttributedString alloc] initWithAttributedString:[attributedString attributedSubstringFromRange:lastCharRange]];
}

[txtDescription setAttributedText:attributedString];

0

是的,这是可能的。然而,我发现在使用Swift Range时,尝试使用NSMutableAttributesString可能会让人头疼。下面的代码将帮助你避免使用Range类,并返回一个用不同颜色突出显示单词的属性字符串。

extension String {
    func getRanges(of string: String) -> [NSRange] {
        var ranges:[NSRange] = []
        if contains(string) {
            let words = self.components(separatedBy: " ")
            var position:Int = 0
            for word in words {
                if word.lowercased() == string.lowercased() {
                    let startIndex = position
                    let endIndex = word.characters.count
                    let range = NSMakeRange(startIndex, endIndex)
                    ranges.append(range)
                }
                position += (word.characters.count + 1) // +1 for space
            }
        }
        return ranges
    }
    func highlight(_ words: [String], this color: UIColor) -> NSMutableAttributedString {
        let attributedString = NSMutableAttributedString(string: self)
        for word in words {
            let ranges = getRanges(of: word)
            for range in ranges {
                attributedString.addAttributes([NSForegroundColorAttributeName: color], range: range)
            }
        }
        return attributedString
    }
}

使用方法:

// The strings you're interested in
let string = "The dog ran after the cat"
let words = ["the", "ran"]

// Highlight words and get back attributed string
let attributedString = string.highlight(words, this: .yellow)

// Set attributed string
textView.attributedText = attributedString

0

在设置了 attributedtext 后,您可以使用所需的值设置 UITextView 的 typingAttributes,以便为输入字段进行设置。

NSDictionary *attribs = @{
    NSForegroundColorAttributeName:[UIColor colorWithHex:kUsernameColor],
    NSFontAttributeName:[UIFont robotoRegularWithSize:40]
};
self.textView.typingAttributes = attribs;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接