2013-07-19 4 views
48

Я использую iOS 6, поэтому атрибутные строки должны быть просты в использовании, не так ли? Ну ... не так много.iOS NSAttributedString на UIButton

Что я хочу сделать:

Используя пользовательский подкласс UIButton (он ничего не делает обычай titleLabel), я хотел бы иметь многострочный, приписываемое название, которое:

  1. Все крышки (я понимаю, что это не часть атрибутов) на первой линии
  2. Bolded на первой линии
  3. Подчеркнуто на первой линии
  4. «Нормальный» вес на второй линии
  5. Non-подчеркнуты на второй линии
  6. Centered на обеих линиях

Я был в состоянии получить # 's 1 через 5 до сих пор (по крайней мере, я думал, что сделал, но текущее тестирование приводит к ошибкам с многострочным текстом), но когда я пытался что-то сделать (что угодно!), чтобы текст был центрирован, мое приложение продолжает сбой. Когда я пытаюсь получить все 6 пунктов, работающих (с помощью различных методов), я получаю следующее сообщение об ошибке/аварии:

Terminating app due to uncaught exception 
'NSInternalInconsistencyException', reason: 
'NSAttributedString invalid for autoresizing, 
it must have a single spanning paragraph style 
(or none) with a non-wrapping lineBreakMode.' 

Основываясь на том, что я пытался, кажется, что у меня может быть один из следующих вариантов, но не оба:

  1. многострочный, по центру этикетки
  2. приписывали этикетки

Я могу жить с той или другой, если я обязательно, но я не могу поверить, что у меня не может быть того, что кажется довольно простой концепцией.

Может кто-нибудь, пожалуйста, скажите мне, что у меня получилось?

Вот последняя итерация кода я пытаюсь:

NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 
[style setAlignment:NSTextAlignmentCenter]; 
[style setLineBreakMode:NSLineBreakByWordWrapping]; 

UIFont *font1 = [UIFont fontWithName:@"HelveticaNeue-Medium" size:20.0f]; 
UIFont *font2 = [UIFont fontWithName:@"HelveticaNeue-Light" size:20.0f]; 
NSDictionary *dict1 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle), 
         NSFontAttributeName:font1}; 
NSDictionary *dict2 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleNone),  
         NSFontAttributeName:font2}; 

NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init]; 
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"LINE 1\n" attributes:dict1]]; 
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"line 2"  attributes:dict2]]; 
[[self buttonToStyle] setAttributedTitle:attString forState:UIControlStateNormal]; 
[[[self buttonToStyle] titleLabel] setNumberOfLines:0]; 
[[[self buttonToStyle] titleLabel] setLineBreakMode:NSLineBreakByWordWrapping]; 
+1

Как насчет стиля UILabel и добавления его к кнопке? – JeffRegan

+0

Разве 'titleLabel' не должен быть' UILabel'? Думаю, я мог бы это сделать, но я все еще чувствую, что это больший молот, чем ДОЛЖЕН быть необходимым. – mbm29414

+0

Это iOS, ничего не имеет смысла ... Я парень. Я перепутал с NSMutableAttributedString некоторое время назад, и это было не что иное, как головные боли. Мой совет заключался в том, чтобы держать все как можно проще и проще. – JeffRegan

ответ

87

Она смотрит на меня, как вы забыли в своем коде, чтобы использовать «стиль» объект, который вы настроили .. вы просто инстанцировали его , Вы должны изменить свой код, чтобы выглядеть следующим образом:

NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; 
[style setAlignment:NSTextAlignmentCenter]; 
[style setLineBreakMode:NSLineBreakByWordWrapping]; 

UIFont *font1 = [UIFont fontWithName:@"HelveticaNeue-Medium" size:20.0f]; 
UIFont *font2 = [UIFont fontWithName:@"HelveticaNeue-Light" size:20.0f]; 
NSDictionary *dict1 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleSingle), 
         NSFontAttributeName:font1, 
         NSParagraphStyleAttributeName:style}; // Added line 
NSDictionary *dict2 = @{NSUnderlineStyleAttributeName:@(NSUnderlineStyleNone), 
         NSFontAttributeName:font2, 
         NSParagraphStyleAttributeName:style}; // Added line 

NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init]; 
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"LINE 1\n" attributes:dict1]]; 
[attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"line 2"  attributes:dict2]]; 
[self.resolveButton setAttributedTitle:attString forState:UIControlStateNormal]; 
[[self.resolveButton titleLabel] setNumberOfLines:0]; 
[[self.resolveButton titleLabel] setLineBreakMode:NSLineBreakByWordWrapping]; 

Обратите внимание, что я только добавил линии, которые определяют NSParagraphStyleAttributeName .. все остальное то же самое .. и это то, что я получаю для кнопки:

enter image description here

И вот он в Swift 3.0

let style = NSMutableParagraphStyle() 
style.alignment = .center 
style.lineBreakMode = .byWordWrapping 

guard 
    let font1 = UIFont(name: "HelveticaNeue-Medium", size: 20), 
    let font2 = UIFont(name: "HelveticaNeue-Light", size: 20) else { return } 

let dict1:[String:Any] = [ 
    NSUnderlineStyleAttributeName:NSUnderlineStyle.styleSingle.rawValue, 
    NSFontAttributeName:font1, 
    NSParagraphStyleAttributeName:style 
] 

let dict2:[String:Any] = [ 
    NSUnderlineStyleAttributeName:NSUnderlineStyle.styleNone.rawValue, 
    NSFontAttributeName:font2, 
    NSParagraphStyleAttributeName:style 
] 

let attString = NSMutableAttributedString() 
attString.append(NSAttributedString(string: "LINE 1", attributes: dict1)) 
attString.append(NSAttributedString(string: "line 2", attributes: dict2)) 

button.setAttributedTitle(attString, for: .normal) 
button.titleLabel?.numberOfLines = 0 
button.titleLabel?.lineBreakMode = .byWordWrapping 
+0

Когда я использую текст Attributed, у кого-нибудь есть решение? –

+0

http://stackoverflow.com/questions/24525224/programmatically-change-title-color-of-uibutton-whose-title-set-as-attributed-in, я получил ответ здесь. –

+0

Как добавить в него цвет? –

2

С Swift 4, вы можете использовать реализацию по UIButton подкласса ниже, для того, чтобы решить вашу проблему:

import UIKit 

class CustomButton: UIButton { 

    required init(title: String, subtitle: String) { 
     super.init(frame: CGRect.zero) 

     let style = NSMutableParagraphStyle() 
     style.alignment = NSTextAlignment.center 
     style.lineBreakMode = NSLineBreakMode.byWordWrapping 

     let titleAttributes: [NSAttributedStringKey : Any] = [ 
      NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue, 
      NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.largeTitle), 
      NSAttributedStringKey.paragraphStyle : style 
     ] 
     let subtitleAttributes = [ 
      NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.body), 
      NSAttributedStringKey.paragraphStyle : style 
     ] 

     let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes) 
     attributedString.append(NSAttributedString(string: "\n")) 
     attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes)) 

     setAttributedTitle(attributedString, for: UIControlState.normal) 
     titleLabel?.numberOfLines = 0 
     titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

} 

Использование:

import UIKit 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let button = CustomButton(title: "Title", subtitle: "Subtitle") 
     button.translatesAutoresizingMaskIntoConstraints = false 
     view.addSubview(button) 

     let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor) 
     let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor) 
     NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint]) 
    } 

} 

качестве альтернатива, если вам действительно нужна кнопка типа system, вы можете использовать следующий код:

import UIKit 

extension UIButton { 

    static func customSystemButton(title: String, subtitle: String) -> UIButton {    
     let style = NSMutableParagraphStyle() 
     style.alignment = NSTextAlignment.center 
     style.lineBreakMode = NSLineBreakMode.byWordWrapping 

     let titleAttributes: [NSAttributedStringKey : Any] = [ 
      NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue, 
      NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.largeTitle), 
      NSAttributedStringKey.paragraphStyle : style 
     ] 
     let subtitleAttributes = [ 
      NSAttributedStringKey.font : UIFont.preferredFont(forTextStyle: UIFontTextStyle.body), 
      NSAttributedStringKey.paragraphStyle : style 
     ] 

     let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes) 
     attributedString.append(NSAttributedString(string: "\n")) 
     attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes)) 

     let button = UIButton(type: UIButtonType.system) 
     button.setAttributedTitle(attributedString, for: UIControlState.normal) 
     button.titleLabel?.numberOfLines = 0 
     button.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping 

     return button 
    } 

} 

Использование:

import UIKit 

class ViewController: UIViewController { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let button = UIButton.customSystemButton(title: "Title", subtitle: "Subtitle") 
     button.translatesAutoresizingMaskIntoConstraints = false 
     view.addSubview(button) 

     let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor) 
     let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor) 
     NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint]) 
    } 

} 

Два снимки экрана ниже показывают отображение результата для UIButton подкласса (слева) и кнопка system (справа):

enter image description here

Смежные вопросы