Настройка цвета переднего плана работает только один раз для NSAttributedString

Телефонная часть строки получает атрибут подчеркивания, но цвет остается красным. Я отделил цвет и подчеркнуть setAttributes() звонки, чтобы прояснить ситуацию, то же самое происходит, когда это один звонок.

    let text = "call "
    let phone = "1800-800-900"

    let attrString = NSMutableAttributedString(string: text + phone, attributes: nil)
    let rangeText = (attrString.string as NSString).range(of: text)
    let rangePhone = (attrString.string as NSString).range(of: phone)

    attrString.setAttributes([NSAttributedStringKey.foregroundColor: UIColor.red],
                             range: rangeText)

    attrString.setAttributes([NSAttributedStringKey.foregroundColor: UIColor.blue],
                             range: rangePhone)

    attrString.setAttributes([NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleSingle.rawValue],
                             range: rangePhone)

2 ответа

Решение

Из документа setAttributes():

Эти новые атрибуты заменяют любые атрибуты, ранее связанные с символами в aRange.

Другими словами, он заменяет их, стирая все ранее установленные, поэтому, когда вы добавляете подчеркивание, он удаляет цвет в этом диапазоне.

Решение, использование addAttributes() вместо setAttributes():

let text = "call "
let phone = "1800-800-900"

let attrString = NSMutableAttributedString(string: text + phone, attributes: nil)
let rangeText = (attrString.string as NSString).range(of: text)
let rangePhone = (attrString.string as NSString).range(of: phone)

attrString.addAttributes([NSAttributedStringKey.foregroundColor: UIColor.red],
                         range: rangeText)

attrString.addAttributes([NSAttributedStringKey.foregroundColor: UIColor.blue],
                         range: rangePhone)

attrString.addAttributes([NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleSingle.rawValue],
                         range: rangePhone)

Другое решение, используйте два NSAttributedString (Я также удаляю NSAttributedStringKey в перечислении)

let textAttrStr = NSAttributedString(string:text, attributes:[.foregroundColor: UIColor.red])
let phoneAttrStr = NSAttributedString(string:phone, attributes:[.foregroundColor: UIColor.blue,
                                                               .underlineStyle: NSUnderlineStyle.styleSingle.rawValue])

let finalAttrStr = NSMutableAttributedString.init(attributedString: textAttrStr)
finalAttrStr.append(phoneAttrStr)

Возможная проблема с первым решением:
range(of:) возвращает диапазон только в первом случае. Другими словами, если text = "1800 " и phone = "18", вы получите нежелательные результаты. так как rangePhone будет от индекса 0 до 1, а не от 7 до 8 в 1800 18, Эта проблема не произойдет во втором.

Вы не должны разделять второй и третий вызов setAttributes, так как последний перезапишет ранее. Объедините стили в одном массиве:

attrString.setAttributes([.foregroundColor: UIColor.blue,
                          .underlineStyle: NSUnderlineStyle.styleSingle.rawValue],
                          range: rangePhone)

Результат:

скриншот результата

Другие вопросы по тегам