Zmienić kolor ciągu za pomocą NSAttributedString?


147

Mam suwak ankiety, który wyświetla następujące ciągi znaków w oparciu o wartość suwaka: „Bardzo zły, zły, ok, dobry, bardzo dobry”.

Oto kod suwaka:

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

Chcę, aby „Bardzo zły” był czerwony, „Zły” był pomarańczowy, „W porządku” był żółty, „Dobrze” i „Bardzo dobrze” był zielony.

Nie rozumiem, jak użyć, NSAttributedStringaby to zrobić.



Masz na myśli UISlider? To nie ma etykiety. Więc w zasadzie chodzi o UILabel z kolorem czcionki? A może chcesz, aby część tekstu została pokolorowana?
Roger,


Użyj tej biblioteki, to drobiazgowo proste. github.com/iOSTechHub/AttributedString
Ashish Chauhan

Odpowiedzi:


196

Nie ma potrzeby używania NSAttributedString. Wystarczy prosta etykieta z odpowiednią textColor. Dodatkowo to proste rozwiązanie będzie działać ze wszystkimi wersjami iOS, nie tylko iOS 6.

Ale jeśli niepotrzebnie chcesz użyć NSAttributedString, możesz zrobić coś takiego:

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
Nie rozumiem wszystkich głosów negatywnych. Moja odpowiedź jest znacznie prostsza niż użycie przypisanego ciągu. OP nie ma potrzeby korzystania NSAttributedStringz tego zadania. Byłoby jedno, gdyby tekst etykiety wymagał wielu atrybutów, ale tak nie jest. Cała etykieta musi mieć jeden kolor na raz.
rmaddy

@ RubénE.Marín Ale w tym problem. OP błędnie pomyślał, że rozwiązanie wymaga użycia NSAttributedString. Więc o to prosili. Prawdziwe pytanie powinno brzmieć „Jak ustawić kolor etykiety na podstawie jej wartości” . Zwróciłem uwagę, że rozwiązanie nie wymaga NSAttributedStringi pokazałem dużo prostszą odpowiedź. OP zgodził się, akceptując moją znacznie prostszą odpowiedź. Gdyby OP naprawdę chciał NSAttributedString, nie zaakceptowaliby mojej odpowiedzi. Nie ma więc powodu do głosów przeciw. Odpowiedziałem na prawdziwe pytanie i PO został zaakceptowany.
rmaddy

24
W takim przypadku rozwiązałbym to pytanie za pomocą NSAttributedString, a następnie wskazałbym Twoje prostsze i wydajniejsze rozwiązanie dla konkretnego przypadku PO. Osoby, które zadają to pytanie, mogą czuć się sfrustrowane Twoim rozwiązaniem, ponieważ szukają sposobów zmiany koloru tekstu w NSAttributedString (i to wyjaśniałoby Twoje głosy negatywne).
Ruben Marin

15
Rubén ma rację: przyszedłem tutaj, ponieważ muszę ustawić kolor w przypisanym ciągu, ponieważ buduję ciąg złożony z przypisanym ciągiem z wieloma kolorami i rozmiarami czcionek. Kluczową informacją, której potrzebowałem, był NSForegroundColorAttributeNameklucz, który trudno mi było znaleźć w dokumentacji Apple.
Erik van der Neut

5
Dziękuję za odpowiedź na pytanie !! nawet jeśli OP tak naprawdę tego nie potrzebował. Tak wiele razy wyszukuję coś w Google, kończę na pytaniu przepełnienia stosu, którego dokładnie szukam, tylko po to, aby odkryć, że mądry dupek odpowiadający na pytanie zdecydował, że OP nie potrzebuje tego, o co prosił tytuł pytania i odpowiedział na zupełnie inne pytanie. Cóż, ludzie w przyszłości pochodzący z wyników wyszukiwania, których może być 1000, w przeciwieństwie do 1 PO, mogą w rzeczywistości chcieć odpowiedzi na pytanie zadane w tytule postu. </rant>
danny

112

Użyj czegoś takiego (nie zaznaczono kompilatora)

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

Hej Anoop, miło cię znowu widzieć! Niepokoiłem kodu, który podałeś. Zastąpiłem self.text.text plikiem self.scanLabel.text, ale otrzymuję błąd w „word”. Próbowałem zamienić go na @ „Very Bad” bez powodzenia.
Adam

Skopiowałem moją odpowiedź stąd stackoverflow.com/questions/14231879/…
Anoop Vaidya

Dzięki, Anoop, ale nie mam szczęścia. - [__ NSCFString _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes:]: nierozpoznany selektor wysłany do instancji 0x1f845af0 2013-01-11 16: 27: 34.939 yellaProto [7829: 907] *** Przerwanie aplikacji z powodu nieprzechwyconego wyjątku „NSCumentAr”: „NSCument” - wyjątek „NSCaliding”. _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes:]: nierozpoznany selektor wysłany do instancji 0x1f845af0 '
Adam


@Morkrom: jeśli zobaczysz drugi komentarz w tej odpowiedzi, to dowiesz się: p
Anoop Vaidya

48

W 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

W 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 

Cieszyć się.


28

Dla Swift 5:

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

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

label.attributedText = attributedString

Dla Swift 4:

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

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

label.attributedText = attributedString

Dla Swift 3:

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

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

label.attributedText = attributedString

7

Możesz tworzyć NSAttributedString

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

LUB NSMutableAttributedStringzastosować atrybuty niestandardowe w zakresach.

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

Dostępne atrybuty: NSAttributedStringKey


AKTUALIZACJA:

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

W Swift 4 NSAttributedStringKeyma statyczną właściwość o nazwie foregroundColor. foregroundColorposiada następującą deklarację:

static let foregroundColor: NSAttributedStringKey

Wartością tego atrybutu jest UIColorobiekt. Użyj tego atrybutu, aby określić kolor tekstu podczas renderowania. Jeśli nie określisz tego atrybutu, tekst będzie wyświetlany na czarno.

Poniższy kod Playground pokazuje, jak ustawić kolor tekstu NSAttributedStringwystąpienia za pomocą foregroundColor:

import UIKit

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

Poniższy kod przedstawia możliwą UIViewControllerimplementację, która polega na NSAttributedStringaktualizacji tekstu i koloru tekstu a UILabelz 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
    }

}

Należy jednak pamiętać, że tak naprawdę nie trzeba używać NSAttributedStringtakiego przykładu, a może po prostu polegać na UILabel„s texti textColorwłaściwości. Dlatego możesz zastąpić swoją updateDisplay()implementację następującym kodem:

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

2

Aktualizacja dla Swift 4.2

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

attributes[.foregroundColor] = UIColor.blue

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

label.attributedText = attributedString

1

Jedna wkładka dla Swift:

NSAttributedString(string: "Red Text", attributes: [.foregroundColor: UIColor.red])
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.