如何使用NSAttributedString更改字符串颜色?

168

我有一个调查用的滑块,基于滑块的值显示以下字符串:"很差,差,可以,好,非常好"。

这是滑块的代码:

- (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 - user529758
你是指UISlider吗?它没有标签。所以基本上是关于带有字体颜色的UILabel?或者你想要一部分文本着色? - Roger
2
可能是如何使用NSAttributedString?的重复问题。 - John Parker
使用这个库,它非常简单。https://github.com/iOSTechHub/AttributedString - Ashish Chauhan
9个回答

214

没有必要使用 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;

4
我不理解所有的负投票。我的答案比使用 attributed string 更为简单。 OP 在此任务中无需使用 NSAttributedString。如果标签的文本需要多个属性,那就另说了。整个标签只需要一种颜色即可。 - rmaddy
@RubénE.Marín 但这就是问题所在。OP错误地认为解决方案需要使用NSAttributedString。所以这就是他们所要求的。真正的问题应该是“基于标签值如何设置标签颜色”。我指出了解决方案不需要NSAttributedString,并提供了一个更简单的答案。而且OP通过接受我的简单答案来证明了这一点。如果OP 真的想要NSAttributedString,他们不会接受我的答案。所以没有理由投票反对。我回答了真正的问题,OP接受了我的答案。 - rmaddy
29
在这种情况下,我会使用NSAttributedString解决问题,然后指出您针对OP特定情况的更简单和高效的解决方案。来到这个问题的人可能会因为寻找如何在NSAttributedString中改变文本颜色(这也可以解释你的负面评价)而感到挫败。 - Ruben Marin
17
Rubén是正确的:我来这里是因为我确实需要在属性字符串中设置颜色,因为我正在构建一个具有多种颜色和字体大小的复合属性字符串。而我所需要的关键信息是NSForegroundColorAttributeName键,在苹果文档中我找了很久都找不到。 - Erik van der Neut
7
感谢您仍然回答这个问题!!即使原帖作者实际上并不需要它。很多时候我在谷歌上搜索一些东西,最终找到了一个完全符合我的需求的 stack overflow 问题,但却发现那个聪明的回答者认为原帖作者实际上并不需要问题标题所问的内容,并回答了一个完全不同的问题。唉,未来的人们从搜索结果中过来,可能会有1,000个人,而不只是一个原帖作者,他们可能确实想要一个解决方案来回答帖子标题中提出的问题。</抱怨> - danny
我是通过谷歌搜索来到这里的,本来预计要根据我在点击链接之前看到的摘录而对这个答案进行负评。很高兴你意识到这不仅仅是关于OP需要什么,还有其他类似问题的人正在寻找的内容。我很高兴你编辑了你的答案,提供了正确的解决方案。+1 - Stunner

116

可以使用类似以下代码的方式(未经编译器检查):

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”处出现了错误。我尝试用@"Very Bad"替换它,但没有成功。 - Adam
我从这里复制了我的答案https://dev59.com/B2Yq5IYBdhLWcg3wvzKm#14231900 - Anoop Vaidya
@Morkrom:如果您看到此答案的第二个评论,那么您就会知道:p - Anoop Vaidya
被踩了。如果你使用了其他地方的答案,请在回答中提到,而不是在评论中。 - Dragos Strugar
@DragosStrugar:我抄袭了答案! - Anoop Vaidya
显示剩余2条评论

59

Swift 4/5 中:

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

享受。


35

针对 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

8

你可以创建NSAttributedString

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

或者使用NSMutableAttributedString 对范围应用自定义属性。

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


更新:

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

5

在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来更新UILabel的文本和文本颜色,从一个UISlider中获取数值:
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,而可以简单地依赖于UILabel的text和textColor属性。因此,您可以将updateDisplay()实现替换为以下代码:
func updateDisplay() {
    label.text = currentStatus.display.text
    label.textColor = currentStatus.display.color
    slider.value = Float(currentStatus.rawValue)
}

5

Swift 5.2更新

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

attributes[.foregroundColor] = UIColor.blue

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

label.attributedText = attributedString

1
一行 Swift 代码:
NSAttributedString(string: "Red Text", attributes: [.foregroundColor: UIColor.red])

0

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

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

结果

..


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