使用 NSAttributedString 更改字符串颜色?

Posted

技术标签:

【中文标题】使用 NSAttributedString 更改字符串颜色?【英文标题】:Change string color with NSAttributedString? 【发布时间】:2012-12-26 13:54:36 【问题描述】:

我有一个用于调查的滑块,它根据滑块的值显示以下字符串:“非常差、差、好的、好、非常好”。

这是滑块的代码:

- (IBAction) sliderValueChanged:(UISlider *)sender 
    scanLabel.text = [NSString stringWithFormat:@" %.f", [sender value]];
    NSArray *texts=[NSArray arrayWithObjects:@"Very Bad", @"Bad", @"Okay", @"Good", @"Very Good", @"Very Good", nil];
    NSInteger sliderValue=[sender value]; //make the slider value in given range integer one.
    self.scanLabel.text=[texts objectAtIndex:sliderValue];

我希望“非常糟糕”为红色,“糟糕”为橙色,“还好”为黄色,“良好”和“非常好”为绿色。

我不明白如何使用NSAttributedString 来完成这项工作。

【问题讨论】:

this 你的意思是 UISlider?那没有标签。所以基本上它是关于带有字体颜色的 UILabel 的?还是您想要部分文本着色? How do you use NSAttributedString?的可能重复 使用这个库,很简单。 github.com/iosTechHub/AttributedString 【参考方案1】:

Swift 5.2 更新

var attributes = [NSAttributedString.Key: AnyObject]()

attributes[.foregroundColor] = UIColor.blue

let attributedString = NSAttributedString(string: "Very Bad",
attributes: attributes)

label.attributedText = attributedString

【讨论】:

【参考方案2】:

我喜欢让事情变得更简单,试试这个

-(NSArray *) reArrangeArrays:(NSArray *)iObjects 
    
    NSMutableArray *Words = [[NSMutableArray alloc] init];
    NSMutableArray *Colors = [[NSMutableArray alloc] init];
    
    CFIndex OneThree = 0;
    CFIndex TwoFour = 1;
    for (CFIndex iCounter = 0; iCounter < iObjects.count; iCounter ++) 
        
        [Words addObject:[iObjects objectAtIndex:OneThree]];
        [Colors addObject:[iObjects objectAtIndex:TwoFour]];
        
        OneThree = OneThree + 2;
        TwoFour = TwoFour + 2;
        
        if (OneThree > iObjects.count || TwoFour > iObjects.count)
            break;
    
    
    return @[[NSArray arrayWithArray:Words],[NSArray arrayWithArray:Colors]];


+(NSMutableAttributedString *) OriginalText:(NSString *)OriginalText WordsAndColors:(NSArray *)WordsAndColors TheRestOfTheTextColor:(UIColor *)TheRestColor 
    
    NSArray *Text = [[self.alloc reArrangeArrays:WordsAndColors] objectAtIndex:0];
    NSArray *Color = [[self.alloc reArrangeArrays:WordsAndColors] objectAtIndex:1];

    NSMutableAttributedString *MutableAttString = [[NSMutableAttributedString alloc] initWithString:OriginalText attributes:@NSForegroundColorAttributeName : TheRestColor];

    NSString *text = OriginalText;

    if (OriginalText != nil) 

    for (NSUInteger Counter = 0; Counter < Color.count; Counter ++) 

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:[NSString stringWithFormat:@"(%@)",[Text objectAtIndex:Counter]] options:kNilOptions error:nil];

    NSRange range = NSMakeRange(0 ,text.length);

    [regex enumerateMatchesInString:text options:kNilOptions range:range usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) 

        NSRange subStringRange = [result rangeAtIndex:0];

        [MutableAttString addAttribute:NSForegroundColorAttributeName value:[Color objectAtIndex:Counter] range:subStringRange];

    ];


    

    return MutableAttString;


这就是使用方法


 NSString *Text = @"Made by @CrazyMind90";
        
 NSMutableAttributedString *AttriString = [ViewController OriginalText:Text
            WordsAndColors:@[
                
            @"Made",UIColor.redColor,
            @"by",UIColor.yellowColor,
            @"@CrazyMind90",UIColor.blueColor,
            
            ]
            
           TheRestOfTheTextColor:UIColor.whiteColor];
        
    
           //Not TextView.text BUT TextView.attributedText
           TextView.attributedText = AttriString;

The result

..

【讨论】:

【参考方案3】:

对于 Swift 5:

var attributes = [NSAttributedString.Key: AnyObject]()
attributes[.foregroundColor] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString

对于 Swift 4:

var attributes = [NSAttributedStringKey: AnyObject]()
attributes[.foregroundColor] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString

对于 Swift 3:

var attributes = [String: AnyObject]()
attributes[NSForegroundColorAttributeName] = UIColor.red

let attributedString = NSAttributedString(string: "Very Bad", attributes: attributes)

label.attributedText = attributedString

【讨论】:

【参考方案4】:

Swift 的一个衬里:

NSAttributedString(string: "Red Text", attributes: [.foregroundColor: UIColor.red])

【讨论】:

【参考方案5】:

您可以创建NSAttributedString

NSDictionary *attributes = @ NSForegroundColorAttributeName : [UIColor redColor] ;
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"My Color String" attributes:attrs];

OR NSMutableAttributedString 将自定义属性与 Ranges 一起应用。

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@%@", methodPrefix, method] attributes: @ NSFontAttributeName : FONT_MYRIADPRO(48) ];
[attributedString addAttribute:NSFontAttributeName value:FONT_MYRIADPRO_SEMIBOLD(48) range:NSMakeRange(methodPrefix.length, method.length)];

可用属性:NSAttributedStringKey


更新:

斯威夫特 5.1

let message: String = greeting + someMessage
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 2.0
    
// Note: UIFont(appFontFamily:ofSize:) is extended init.
let regularAttributes: [NSAttributedString.Key : Any] = [.font : UIFont(appFontFamily: .regular, ofSize: 15)!, .paragraphStyle : paragraphStyle]
let boldAttributes = [NSAttributedString.Key.font : UIFont(appFontFamily: .semiBold, ofSize: 15)!]

let mutableString = NSMutableAttributedString(string: message, attributes: regularAttributes)
mutableString.addAttributes(boldAttributes, range: NSMakeRange(0, greeting.count))

【讨论】:

【参考方案6】:

Swift 4 中:

// Custom color
let greenColor = UIColor(red: 10/255, green: 190/255, blue: 50/255, alpha: 1)
// create the attributed colour
let attributedStringColor = [NSAttributedStringKey.foregroundColor : greenColor];
// create the attributed string
let attributedString = NSAttributedString(string: "Hello World!", attributes: attributedStringColor)
// Set the label
label.attributedText = attributedString

Swift 3 中:

// Custom color
let greenColor = UIColor(red: 10/255, green: 190/255, blue: 50/255, alpha: 1)
// create the attributed color
let attributedStringColor : NSDictionary = [NSForegroundColorAttributeName : greenColor];
// create the attributed string
let attributedString = NSAttributedString(string: "Hello World!", attributes: attributedStringColor as? [String : AnyObject])
// Set the label
label.attributedText = attributedString 

享受吧。

【讨论】:

【参考方案7】:

在 Swift 4 中,NSAttributedStringKey 有一个名为 foregroundColor 的静态属性。 foregroundColor 有以下声明:

static let foregroundColor: NSAttributedStringKey

这个属性的值是一个UIColor 对象。使用此属性可在渲染期间指定文本的颜色。如果不指定此属性,则文本呈现为黑色。

以下 Playground 代码显示了如何使用 foregroundColor 设置 NSAttributedString 实例的文本颜色:

import UIKit

let string = "Some text"
let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
let attributedString = NSAttributedString(string: string, attributes: attributes)

下面的代码显示了一个可能的UIViewController 实现,它依赖于NSAttributedString 以便从UISlider 更新UILabel 的文本和文本颜色:

import UIKit

enum Status: Int 
    case veryBad = 0, bad, okay, good, veryGood

    var display: (text: String, color: UIColor) 
        switch self 
        case .veryBad:  return ("Very bad", .red)
        case .bad:      return ("Bad", .orange)
        case .okay:     return ("Okay", .yellow)
        case .good:     return ("Good", .green)
        case .veryGood: return ("Very good", .blue)
        
    

    static let minimumValue = Status.veryBad.rawValue
    static let maximumValue = Status.veryGood.rawValue

final class ViewController: UIViewController 

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var slider: UISlider!
    var currentStatus: Status = Status.veryBad 
        didSet 
            // currentStatus is our model. Observe its changes to update our display
            updateDisplay()
        
    

    override func viewDidLoad() 
        super.viewDidLoad()

        // Prepare slider
        slider.minimumValue = Float(Status.minimumValue)
        slider.maximumValue = Float(Status.maximumValue)

        // Set display
        updateDisplay()
    

    func updateDisplay() 
        let attributes = [NSAttributedStringKey.foregroundColor : currentStatus.display.color]
        let attributedString = NSAttributedString(string: currentStatus.display.text, attributes: attributes)
        label.attributedText = attributedString
        slider.value = Float(currentStatus.rawValue)
    

    @IBAction func updateCurrentStatus(_ sender: UISlider) 
        let value = Int(sender.value.rounded())
        guard let status = Status(rawValue: value) else  fatalError("Could not get Status object from value") 
        currentStatus = status
    


但是请注意,对于这样的示例,您实际上并不需要使用NSAttributedString,而可以简单地依赖UILabeltexttextColor 属性。因此,您可以将 updateDisplay() 实现替换为以下代码:

func updateDisplay() 
    label.text = currentStatus.display.text
    label.textColor = currentStatus.display.color
    slider.value = Float(currentStatus.rawValue)

【讨论】:

【参考方案8】:

没有必要使用NSAttributedString。您所需要的只是一个带有正确textColor 的简单标签。此外,这个简单的解决方案适用于所有版本的 iOS,而不仅仅是 iOS 6。

但如果你不必要地希望使用NSAttributedString,你可以这样做:

UIColor *color = [UIColor redColor]; // select needed color
NSString *string = ... // the string to colorize
NSDictionary *attrs = @ NSForegroundColorAttributeName : color ;
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:string attributes:attrs];
self.scanLabel.attributedText = attrStr;

【讨论】:

我不明白所有的反对票。我的答案比使用属性字符串要简单得多。 OP 无需为此任务使用NSAttributedString。如果标签的文本需要多个属性但事实并非如此,那将是一回事。整个标签一次必须是一种颜色。 @RubénE.Marín 但这就是问题所在。 OP 错误地认为解决方案需要使用NSAttributedString。所以这就是他们所要求的。真正的问题应该是“如何根据标签的值设置标签的颜色”。我指出该解决方案不需要NSAttributedString,并给出了一个更简单的答案。 OP同意接受我更简单的答案。如果 OP 真的 想要NSAttributedString,他们就不会接受我的回答。因此,没有理由投反对票。我回答了真正的问题并接受了 OP。 在这种情况下,我会用 NSAttributedString 解决这个问题,然后,我会针对 OP 的特定情况指出你更简单、更有效的解决方案。提出这个问题的人可能会对您的解决方案感到沮丧,因为他们正在寻找更改 NSAttributedString 上的文本颜色的方法(这可以解释您的反对票)。 Rubén 是对的:我来到这里是因为我确实需要在属性字符串中设置颜色,因为我正在构建一个具有多种颜色和字体大小的复合属性字符串。我需要的关键信息是 NSForegroundColorAttributeName 密钥,我很难在 Apple 文档中找到它。 感谢您仍然回答问题!即使OP实际上并不需要它。很多次我用谷歌搜索了一些东西,最终遇到了一个堆栈溢出问题,这正是我正在寻找的,只是发现回答问题的聪明人决定 OP 实际上并不需要问题标题所要求的内容,并且回答了一个完全不同的问题。好吧,未来来自搜索结果的人(其中可能有 1000 个而不是 1 个 OP)实际上可能想要解决帖子标题中提出的问题。 【参考方案9】:

使用类似的东西(未检查编译器)

NSMutableAttributedString *string = [[NSMutableAttributedString alloc]initWithString:self.text.text];
NSRange range=[self.myLabel.text rangeOfString:texts[sliderValue]]; //myLabel is the outlet from where you will get the text, it can be same or different

NSArray *colors=@[[UIColor redColor],
                  [UIColor redColor],
                  [UIColor yellowColor],
                  [UIColor greenColor]
                 ];

[string addAttribute:NSForegroundColorAttributeName 
               value:colors[sliderValue] 
               range:range];           

[self.scanLabel setAttributedText:texts[sliderValue]];

【讨论】:

嗨 Anoop,很高兴再次见到你!我使用您提供的代码,我用 self.scanLabel.text 替换了 self.text.text,但在“word”处出现错误。我尝试用@“非常糟糕”替换它,但没有成功。 我从这里复制了我的答案***.com/questions/14231879/… 感谢 Anoop,但我没有运气。 -[__NSCFString _ui_synthesizeAttributedSubstringFromRange:usingDefaultAttributes:]:无法识别的选择器发送到实例 0x1f845af0 2013-01-11 16:27:34.939yellaProto[7829:907] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:'-[__NSCFString _ui_synthesizeAttributedSubstringFromRange:usingDefaultAttributes:]: 无法识别的选择器发送到实例 0x1f845af0' 只是想弄清楚“文本”是什么 @Morkrom:如果您在此答案中看到第二条评论,那么您将了解:p

以上是关于使用 NSAttributedString 更改字符串颜色?的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSAttributedString 更改字符串的颜色和字体

更改 NSAttributedString html 链接颜色

仅更改 NSAttributedString 的字体大小

使用 NSAttributedString 设置字体

在不丢失 Html 样式的情况下更改 NSAttributedString 中的字体大小 - Swift

富文本常用封装(NSAttributedString)