Змінити колір рядка за допомогою NSAttributedString?


147

У мене є слайдер для опитування, який відображає такі рядки на основі значення слайдера: "Дуже погано, погано, добре, добре, дуже добре".

Ось код для слайдера:

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



Ви маєте на увазі UISlider? Це не має етикетки. Так в основному це про UILabel з кольором шрифту? Або ви хочете, щоб частина тексту була кольорова?
Роджер


Використовуйте цю бібліотеку, це просто дрібно. github.com/iOSTechHub/AttributedString
Ashish Chauhan

Відповіді:


196

Немає потреби у використанні 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
Я не розумію всіх голосів, що були прихильні. Моя відповідь набагато простіша, ніж використання атрибутивного рядка. ОП не потребує використання NSAttributedStringцього завдання. Було б одне, якщо текст мітки потребував декількох атрибутів, але це не так. Вся етикетка повинна бути одного кольору за один раз.
rmaddy

@ RubénE.Marín Але в цьому проблема. ОП помилково подумав, що рішення потрібно використовувати NSAttributedString. Тож це вони просили. Справжнє питання повинно було бути "Як встановити колір етикетки на основі його значення" . Я зазначив, що рішення не потребує, NSAttributedStringі показав набагато простішу відповідь. І ОП погодилася, прийнявши мою набагато простішу відповідь. Якби ОП дуже хотіла NSAttributedString, вони б не прийняли мою відповідь. Тож немає причин для зниження голосів. Я відповів на справжнє запитання і ОП прийняв.
rmaddy

24
У такому випадку я вирішив би питання з NSAttributedString, і після цього я зазначив би ваше простіше та ефективніше рішення для конкретного випадку ОП. Люди, які стикаються з цим питанням, можуть відчути розчарування від вашого рішення, тому що вони шукають способи змінити колір тексту на NSAttributedString (і це пояснить ваші голоси).
Рубен Марін

15
Рубен має рацію: я прийшов сюди, тому що мені потрібно встановити колір в атрибутованій рядку, тому що я будую складний атрибутивний рядок з кількома кольорами та розмірами шрифту. І ключовою інформацією, яка мені була потрібна, був NSForegroundColorAttributeNameключ, який мені важко було знайти в документах Apple.
Ерік ван дер Нойт

5
Дякую, що все-таки відповідали на питання !! навіть якщо ОП насправді цього не потребував. Так багато разів я щось гуглю, і закінчую питання про переповнення стека, саме це я шукаю, лише щоб дізнатися, що мудрий задниця, відповідаючи на питання, вирішив, що ОП насправді не потребує того, що запитувала назва запитання, і відповів на зовсім інше запитання. Ну, а люди в майбутньому, отримані з результатів пошуку, яких може бути 1000, на відміну від 1 ОП, можуть насправді захотіти вирішити питання, задане в заголовку посади. </rant>
danny

112

Використовуйте щось подібне (не встановлений компілятор)

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

Ей, Ануоп, рада бачити тебе знову! Я шанував код, який ви надали, я замінив self.text.text на self.scanLabel.text, але я отримую помилку при "word". Я спробував замінити його на @ "Дуже погано", не пощастивши.
Адам

Я скопіював свою відповідь звідси stackoverflow.com/questions/14231879/…
Anoop Vaidya

Дякую Anoop, але мені не пощастило. - [__ NSCFString _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes]: невизнаний селектор спрямований наприклад 0x1f845af0 2013-01-11 16: 27: 34,939 yellaProto [7829: 907] *** згоди додатки з - за неперехваченное виключення 'NSInvalidArgumentException', причина: «- [__ NSCFString _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes:]: нерозпізнаний селектор надісланий до екземпляра 0x1f845af0 '
Адам

Просто спробуйте розібратися, що таке "тексти"
Morkrom

@Morkrom: якщо ви побачите другий коментар у цій відповіді, тоді ви дізнаєтесь: p
Anoop Vaidya

48

У 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 

Насолоджуйтесь.


28

Для 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

7

Ви можете створити 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


ОНОВЛЕННЯ:

Швидкий 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об’єкт. Використовуйте цей атрибут, щоб вказати колір тексту під час візуалізації. Якщо цей атрибут не вказаний, текст відображається чорним кольором.

У наступному коді ігрової майданчика показано, як встановити колір тексту для NSAttributedStringекземпляра за допомогою foregroundColor:

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«s textі textColorвластивості. Тому ви можете замінити свою updateDisplay()реалізацію наступним кодом:

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

2

Оновлення для Swift 4.2

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

attributes[.foregroundColor] = UIColor.blue

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

label.attributedText = attributedString

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.