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ć.

Adam
źródło
to
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,
2
możliwy duplikat Jak używasz NSAttributedString?
John Parker,
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;
rmaddy
źródło
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]];
Anoop Vaidya
źródło
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
Po prostu
spróbuj sobie wyobrazić,
@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ę.

App Dev Guy
źródło
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
pableiros
źródło
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))
Lal Krishna
źródło
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)
}
Imanou Petit
źródło
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
Mithra Singam
źródło
1

Jedna wkładka dla Swift:

NSAttributedString(string: "Red Text", attributes: [.foregroundColor: UIColor.red])
Fedotchenco Denis
źródło