iOS NSAttributedString on UIButton

前端 未结 3 489
谎友^
谎友^ 2020-12-04 13:14

I\'m using iOS 6, so attributed strings should be easy to use, right? Well... not so much.

What I want to do:

Using a custom subclass of

相关标签:
3条回答
  • 2020-12-04 13:31

    Two line UIButton with NSAttributedString title in Swift 5.1:

    func customizeSubscribeButton() {
        subscribeButton.titleLabel?.numberOfLines = 2
        let title = NSMutableAttributedString()
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = .center
        let part1 = NSAttributedString(string: "SUBSCRIBE FOR 12 MONTH\n",
                                       attributes: [NSAttributedString.Key.foregroundColor: UIColor.white,
                                                    NSAttributedString.Key.font: UIFont.systemFont(ofSize: 24, weight: .semibold),
                                                    NSAttributedString.Key.paragraphStyle: paragraphStyle])
        let part2 = NSAttributedString(string: "999.00 RUB ECONOMY 85%",
                                       attributes: [NSAttributedString.Key.foregroundColor: UIColor.white,
                                                    NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12, weight: .light),
                                                    NSAttributedString.Key.paragraphStyle: paragraphStyle])
        title.append(part1)
        title.append(part2)
        subscribeButton.setAttributedTitle(title, for: .normal)
    }
    
    0 讨论(0)
  • 2020-12-04 13:36

    With Swift 5.1 and iOS 13.1, you can use the UIButton subclass implementation below in order to solve your problem:

    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: [NSAttributedString.Key : Any] = [
                NSAttributedString.Key.foregroundColor: UIColor.label,
                NSAttributedString.Key.underlineStyle : NSUnderlineStyle.single.rawValue,
                NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.largeTitle),
                NSAttributedString.Key.paragraphStyle : style
            ]
            let subtitleAttributes = [
                NSAttributedString.Key.foregroundColor: UIColor.label,
                NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body),
                NSAttributedString.Key.paragraphStyle : style
            ]
    
            let attributedString = NSMutableAttributedString(string: title, attributes: titleAttributes)
            attributedString.append(NSAttributedString(string: "\n"))
            attributedString.append(NSAttributedString(string: subtitle, attributes: subtitleAttributes))
    
            setAttributedTitle(attributedString, for: UIControl.State.normal)
            titleLabel?.numberOfLines = 0
            titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
    }
    

    Usage:

    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])
        }
    
    }
    

    As an alternative if you really need a button of type system, you may use the following code:

    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: [NSAttributedString.Key : Any] = [
                NSAttributedString.Key.underlineStyle : NSUnderlineStyle.single.rawValue,
                NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.largeTitle),
                NSAttributedString.Key.paragraphStyle : style
            ]
            let subtitleAttributes = [
                NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body),
                NSAttributedString.Key.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: UIButton.ButtonType.system)
            button.setAttributedTitle(attributedString, for: UIControl.State.normal)
            button.titleLabel?.numberOfLines = 0
            button.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping
    
            return button
        }
    
    }
    

    Usage:

    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])
        }
    
    }
    

    The two screen shots below show the result display for the UIButton subclass (on the left) and for the system type button (on the right):

    0 讨论(0)
  • 2020-12-04 13:48

    It looks to me like you forgot in your code to use the "style" object that you set up.. you just instantiated it. You should modify your code to look like this:

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

    Note that I only added the lines that define the NSParagraphStyleAttributeName.. everything else is the same.. and this is what I get for the button:

    enter image description here

    And here it is in 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 讨论(0)
提交回复
热议问题