Изменить цвет строки с 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 с цветом шрифта? Или вы хотите, чтобы часть текста была цветной?
Роджер
2
Возможный дубликат Как вы используете NSAttributedString?
Джон Паркер
Используйте эту библиотеку, это просто. github.com/iOSTechHub/AttributedString
Ашиш Чаухан

Ответы:

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;
rmaddy
источник
4
Я не понимаю всех отрицательных голосов. Мой ответ намного проще, чем использование приписанной строки. ОП не нужно использовать NSAttributedStringдля этой задачи. Было бы одно, если бы текст метки нуждался в нескольких атрибутах, но это не так. Вся этикетка должна быть одного цвета за раз.
rmaddy
@ RubénE.Marín Но это проблема. ОП ошибочно полагал, что решение требует использования NSAttributedString. Так вот что они просили. Реальный вопрос должен был быть «Как установить цвет метки на основе ее значения» . Я указал, что решение не требует NSAttributedStringи показал гораздо более простой ответ. И ОП согласился, приняв мой гораздо более простой ответ. Если бы ОП действительно хотел NSAttributedString, они бы не приняли мой ответ. Так что нет причин для отрицательных голосов. Я ответил на истинный вопрос и ОП принял.
rmaddy
24
В этом случае я бы решил вопрос с NSAttributedString, и после этого я бы указал на ваше более простое и эффективное решение для конкретного случая OP. Люди, приходящие на этот вопрос, могут разочароваться вашим решением, потому что они ищут способы изменить цвет текста на NSAttributedString (и это объяснило бы ваши отрицательные голоса).
Рубен Марин
15
Рубен прав: я пришел сюда, потому что мне нужно установить цвет в атрибутивной строке, потому что я строю составную атрибутивную строку с несколькими цветами и размерами шрифта. И ключевым элементом информации, который мне был нужен, был NSForegroundColorAttributeNameключ, который мне было трудно найти в документации Apple.
Эрик ван дер Нойт
5
Спасибо, что все еще отвечаете на вопрос !! даже если ОП на самом деле это не нужно. Очень много раз я что-то гуглял, в конечном итоге на вопрос о переполнении стека, это именно то, что я искал, только чтобы обнаружить, что мудрый ответ на вопрос решил, что ОП на самом деле не нужно то, о чем просил заголовок вопроса, и ответил на совершенно другой вопрос. Что ж, люди в будущем, получающие результаты поиска, которых может быть 1000, а не 1 ОП, могут на самом деле захотеть решить вопрос, заданный в заголовке поста. </ rant>
Дэнни,
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]];
Anoop Vaidya
источник
Эй, Anoop, рад видеть тебя снова! Я проверил код, который вы предоставили, я заменил self.text.text на self.scanLabel.text, но я получаю сообщение об ошибке «word». Я попытался заменить его на @ "Very Bad", но безуспешно.
Адам
Я скопировал свой ответ отсюда stackoverflow.com/questions/14231879/…
Anoop Vaidya
Спасибо Anoop, но мне не повезло. - [__NSCFString _ui_synthesizeAttributedSubstringFromRange: usingDefaultAttributes:]: нераспознанный селектор, отправленный экземпляру 0x1f845af0 2013-01-11 16: 27: 34.939 yellaProto [7829: 907] *** Завершение работы приложения из-за непредусмотренной причины 'исключительная ситуация' - исключение ___ NSF _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 

Наслаждаться.

App Dev Guy
источник
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
pableiros
источник
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


ОБНОВИТЬ:

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

В Swift 4 NSAttributedStringKeyимеет статическое свойство с именем foregroundColor. foregroundColorимеет следующую декларацию:

static let foregroundColor: NSAttributedStringKey

Значением этого атрибута является UIColorобъект. Используйте этот атрибут, чтобы указать цвет текста во время рендеринга. Если этот атрибут не указан, текст отображается черным цветом.

Следующий код Playground показывает, как установить цвет текста NSAttributedStringэкземпляра с помощью foregroundColor:

import UIKit

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

В приведенном ниже коде показана возможная UIViewControllerреализация, которая используется NSAttributedStringдля обновления текста и цвета текста a UILabelиз 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
    }

}

Тем не менее, обратите внимание, что вам не нужно использовать NSAttributedStringдля такого примера, и вы можете просто полагаться на UILabels textи textColorсвойства. Поэтому вы можете заменить свою updateDisplay()реализацию следующим кодом:

func updateDisplay() {
    label.text = currentStatus.display.text
    label.textColor = currentStatus.display.color
    slider.value = Float(currentStatus.rawValue)
}
Imanou Petit
источник
2

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

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

attributes[.foregroundColor] = UIColor.blue

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

label.attributedText = attributedString
Митра Сингам
источник
1

Один лайнер для Swift:

NSAttributedString(string: "Red Text", attributes: [.foregroundColor: UIColor.red])
Федотченко Денис
источник