【问题标题】:Change string color with NSAttributedString?使用 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 来完成这项工作。

【问题讨论】:

标签: ios cocoa-touch nsattributedstring


【解决方案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”处出现错误。我尝试用@“非常糟糕”替换它,但没有成功。
                • 我从这里复制了我的答案stackoverflow.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
                猜你喜欢
                • 1970-01-01
                • 2013-10-08
                • 2012-04-13
                • 1970-01-01
                • 1970-01-01
                • 2013-03-30
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多