Alterar a cor da string com NSAttributedString?

147

Eu tenho um controle deslizante para uma pesquisa que exibe as seguintes seqüências de caracteres com base no valor do controle deslizante: "Muito ruim, ruim, ok, bom, muito bom".

Aqui está o código para o controle deslizante:

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

Quero que "Muito Ruim" seja vermelho, "Ruim" seja laranja, "Ok" seja amarelo, "Bom" e "Muito Bom" sejam verdes.

Eu não entendo como usar NSAttributedStringpara fazer isso.

Adão
fonte
Você quer dizer um UISlider? Isso não tem rótulo. Então basicamente é um UILabel com uma cor de fonte? Ou você quer uma parte do texto colorida?
Roger Roger
2
possível duplicata de Como você usa NSAttributedString?
John Parker
Use esta biblioteca, é muito simples. github.com/iOSTechHub/AttributedString
Ashish Chauhan #

Respostas:

196

Não há necessidade de usar NSAttributedString. Tudo que você precisa é de uma etiqueta simples com a devida textColor. Além disso, esta solução simples funcionará com todas as versões do iOS, não apenas com o iOS 6.

Mas se você deseja usar desnecessariamente NSAttributedString, pode fazer algo assim:

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;
rmaddy
fonte
4
Eu não entendo todos os votos negativos. Minha resposta é muito mais simples do que usar uma string atribuída. O OP não precisa usar NSAttributedStringpara esta tarefa. Seria uma coisa se o texto do rótulo precisasse de vários atributos, mas não. O rótulo inteiro precisa ter uma cor de cada vez.
rmaddy
@ RubénE.Marín Mas esse é o problema. O OP pensou erroneamente que a solução exigia o uso NSAttributedString. Então é isso que eles pediram. A verdadeira questão deveria ter sido "Como definir a cor do rótulo com base em seu valor" . Eu indiquei que a solução não requer NSAttributedStringe mostrou uma resposta muito mais simples. E o OP concordou em aceitar minha resposta muito mais simples. Se o OP realmente quisesse NSAttributedString, eles não teriam aceitado minha resposta. Portanto, não há razão para os votos negativos. Respondi à verdadeira pergunta e o OP aceitou.
rmaddy
24
Nesse caso, eu teria resolvido a questão com NSAttributedString e, depois disso, teria apontado sua solução mais simples e mais eficiente para o caso específico do OP. As pessoas que chegam a essa pergunta podem se sentir frustradas com sua solução, porque estão procurando maneiras de alterar a cor do texto em NSAttributedString (e isso explicaria seus votos negativos).
Ruben Marin
15
Rubén está certo: vim aqui porque preciso definir a cor em uma sequência atribuída, porque estou construindo uma sequência atribuída composta com várias cores e tamanhos de fonte. E a principal informação que eu precisava era a NSForegroundColorAttributeNamechave, que eu tive dificuldade em encontrar nos documentos da Apple.
Erik van der Neut
5
Obrigado por ainda responder à pergunta !! mesmo que o OP realmente não precisasse. Muitas vezes, pesquiso alguma coisa no google, acabo em uma pergunta de estouro de pilha que é exatamente o que estou procurando, apenas para descobrir que o idiota que respondeu à pergunta decidiu que o OP realmente não precisava do que o título da pergunta estava pedindo e respondeu a uma pergunta completamente diferente. Bem, no futuro, as pessoas provenientes de resultados de pesquisa, das quais pode haver milhares, em oposição ao 1 OP, podem realmente querer uma solução para a pergunta feita no título do post. </rant>
danny
112

Use algo parecido com isto (não compilado verificado)

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 Vaidya
fonte
Hey Anoop, prazer em vê-lo novamente! Treidei o código que você forneceu, substituí self.text.text por self.scanLabel.text, mas estou recebendo um erro em "word". Tentei substituí-lo por @ "Very Bad" sem sorte.
Adam
Copiei minha resposta aqui stackoverflow.com/questions/14231879/…
Anoop Vaidya
Obrigado Anoop, mas sem sorte para mim. - [__ NSCFString _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes:]: seletor não reconhecido enviado para a instância 0x1f845af0 2013-01-11 16: 27: 34.939 yellaProto [7829: 907] *** Finalizando o aplicativo devido à exceção não detectada 'NSInvalidArgumentException:' NSInvalidArgumentEx: _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes:]: seletor não reconhecido enviado para a instância 0x1f845af0 '
Adam
Apenas tentando figura otu o que "textos"
Morkrom
@Morkrom: se você vê 2º comentário nesta resposta, então você vai começar a saber: p
Anoop Vaidya
48

No 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

No 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 

Aproveitar.

App Dev Guy
fonte
28

Para o Swift 5:

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

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

label.attributedText = attributedString

Para o Swift 4:

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

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

label.attributedText = attributedString

Para o Swift 3:

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

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

label.attributedText = attributedString
pableiros
fonte
7

Você pode criar NSAttributedString

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

OU NSMutableAttributedStringpara aplicar atributos personalizados com intervalos.

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)];

Atributos disponíveis: NSAttributedStringKey


ATUALIZAR:

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))
Lal Krishna
fonte
5

Com o Swift 4, NSAttributedStringKeytem uma propriedade estática chamada foregroundColor. foregroundColortem a seguinte declaração:

static let foregroundColor: NSAttributedStringKey

O valor desse atributo é um UIColorobjeto. Use este atributo para especificar a cor do texto durante a renderização. Se você não especificar este atributo, o texto será renderizado em preto.

O seguinte código do Playground mostra como definir a cor do texto de uma NSAttributedStringinstância com foregroundColor:

import UIKit

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

O código abaixo mostra uma possível UIViewControllerimplementação que se baseia NSAttributedStringpara atualizar o texto e a cor do texto de a UILabelde a 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
    }

}

Note no entanto que você realmente não precisa usar NSAttributedStringpara tal um exemplo e pode simplesmente confiar em UILabel's texte textColorpropriedades. Portanto, você pode substituir sua updateDisplay()implementação pelo seguinte código:

func updateDisplay() {
    label.text = currentStatus.display.text
    label.textColor = currentStatus.display.color
    slider.value = Float(currentStatus.rawValue)
}
Imanou Petit
fonte
2

Atualização para o Swift 4.2

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

attributes[.foregroundColor] = UIColor.blue

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

label.attributedText = attributedString
Mithra Singam
fonte
1

Um forro para Swift:

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