Multiline UIButton autosize per line

I want to use the standard UIButton but the text I want to put on the UIButton has...

  • ... multiple lines (each line is different string) and ...
  • ... each line should have different font and size that ...
  • ... automatically resizes font to fit the button width (not height to make it a bit easier)
  • 在这里输入图像描述

    So, even tough I would like to set the (preferred) font size for each line, I want the font-size to automatically size down so that each separate line fits nicely in the UIButton (=same behaviour as the UILabel AutoShrink / Minimum Font Scale).

    What I don't want:

    I do not want to start adding UILabels to the UIButton (as subview for example) or using IB put UILabels on a scene and just draw an UIButton around it (why: I want the standard UIButton highlighting behaviour)

    What I want:

    A clean solution using an attributed string, that given the width scales down the font (updates the attributed string I guess), line-by-line if required.

    My idea, implement a function like this:

        func addToAttributedString(attString : NSMutableAttributedString, plainString : String, font : UIFont, preferredSize : CGFloat, maxWidth : CGFloat)
    

    And then I could make the attributed string by calling this with text 1,2,3... and insert a newline (n) between them.

    Any ideas?


    sizeToFit() will help you to adjust height as the text.

        var str : NSMutableAttributedString = NSMutableAttributedString(string: "BlanBlanBlanBlanBlanBlanBlanBlanBlanBlanBlanBlanBlanBlanBlanBlanBlanBla")
        str.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(20), range: NSRange(location: 13,length: 3))
        button.setAttributedTitle(str, forState: UIControlState.Normal)
        button.titleLabel!.lineBreakMode = .ByWordWrapping
        button.titleLabel?.textAlignment = .Center
        button.titleLabel?.adjustsFontSizeToFitWidth = true
        button.sizeToFit()
        button.layoutIfNeeded()
    

    Working with your code too :

        var attrString = NSMutableAttributedString()
        addNewLineToAttributedString(attrString, plainString: "Big title", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Smaller text", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Smaller smaller text", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Smaller Smaller Smaller text", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Smaller Smaller Smaller text", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Big title", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Big title", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Smaller Smaller Smaller text", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Smaller Smaller Smaller text", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Smaller Smaller Smaller text", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        addNewLineToAttributedString(attrString, plainString: "Smaller Smaller Smaller text", font: UIFont.systemFontOfSize(10), preferredSize: 50, maxWidth: 100)
        button.setAttributedTitle(attrString, forState: UIControlState.Normal)
        button.titleLabel!.lineBreakMode = .ByWordWrapping
        button.titleLabel?.textAlignment = .Center
        button.titleLabel?.adjustsFontSizeToFitWidth = true
        button.sizeToFit()
        button.layoutIfNeeded()
    

    在这里输入图像描述


    You can achieve it using Storyboard it self. Just perform this steps

    1: Change Button Type from System to Custome .

    在这里输入图像描述

    2: Change Button Title From plain to attributed .

    3: Enter the text in textArea and press Alt + Enter when u need a newLine. see image it will break my text into 3 line .

    在这里输入图像描述

    4: Now set line break mode to Character Wrap .

    在这里输入图像描述

    NOTE: If you don't see the text in different line in storyboard change the text align from Align natural to Align left . set as select portion in image

    5: Now select individual line and set font. U can also change the textColor.

    在这里输入图像描述

    6: Repeat Step5 for each line.

    here is my simulator output:

    在这里输入图像描述


    Figured out a solution (have a look at my blog http://www.hixfield.net/blog/2015/06/multiline-uibutton-with-each-line-resized-to-fit-width/ for more info)

    class ViewController: UIViewController {
    
        //the button that we are formatting
        @IBOutlet weak var btn: UIButton!
    
        //setup our button in the will appear function
        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)
            setupBtn()
        }
    
        //function that does the magic
        func setupBtn() {
            btn.titleLabel?.lineBreakMode=NSLineBreakMode.ByWordWrapping
            var attrString = NSMutableAttributedString()
            var attr = [NSFontAttributeName : UIFont.systemFontOfSize(10)]
            attrString += (NSMutableAttributedString(string : "Big title", font: UIFont.systemFontOfSize(50), maxWidth: 100)! + "n" )
            attrString += (NSMutableAttributedString(string : "Smaller text", font: UIFont.systemFontOfSize(50), maxWidth: 100)!  + "n" )
            attrString += (NSMutableAttributedString(string : "Smaller smaller text", font: UIFont.systemFontOfSize(80), maxWidth: 100)! + "n" )
            btn.setAttributedTitle(attrString, forState: UIControlState.Normal)
        }
    }
    
    //************************
    
    extension NSMutableAttributedString {
        /**Makes an attributes string with the specified (plain) string and font but resizes the font smaller
        to fit the width if required. Can return nil, if there is no way to make it fit*/
        convenience init?(string : String, font : UIFont, maxWidth : CGFloat){
            self.init()
            for var size = font.pointSize ; size>1 ; size-- {
                let attrs = [NSFontAttributeName : font.fontWithSize(size)]
                let attrString = NSAttributedString(string: string, attributes: attrs)
                if attrString.size().width <= maxWidth {
                    self.setAttributedString(attrString)
                    return
                }
            }
            return nil
        }
    }
    
    //************************
    
    public func += (inout left: NSMutableAttributedString, right: NSAttributedString) {
        left.appendAttributedString(right)
    }
    
    public func + (left: NSAttributedString, right: NSAttributedString) -> NSAttributedString {
        var result  = NSMutableAttributedString(attributedString: right)
        result.appendAttributedString(right)
        return result
    }
    
    public func + (left: NSAttributedString, right: String) -> NSAttributedString {
        var result  = NSMutableAttributedString(attributedString: left)
        result.appendAttributedString(NSAttributedString(string: right))
        return result
    }
    

    在这里输入图像描述

    链接地址: http://www.djcxy.com/p/28222.html

    上一篇: 行UIButtons

    下一篇: 多行UIButton每行自动调整大小