Multiline UIButton and autolayout

后端 未结 16 1454
无人共我
无人共我 2020-12-03 13:08

I have created a view controller that looks like this:

\"enter

I want the two

相关标签:
16条回答
  • 2020-12-03 13:49

    add the missing constraints:

    if let label = button.titleLabel {
    
        button.addConstraint(NSLayoutConstraint(item: label, attribute: .top, relatedBy: .equal, toItem: button, attribute: .top, multiplier: 1.0, constant: 0.0))
        button.addConstraint(NSLayoutConstraint(item: label, attribute: .bottom, relatedBy: .equal, toItem: button, attribute: .bottom, multiplier: 1.0, constant: 0.0))
    }
    
    0 讨论(0)
  • 2020-12-03 13:49

    Version, which also taking into account titleEdgeInsets and not overrides standard button behaviour unless titleLabel?.numberOfLines set to zero and button image set to nil.

    open class Button: UIButton {
    
       override open var intrinsicContentSize: CGSize {
          if let titleLabel = titleLabel, titleLabel.numberOfLines == 0, image == nil {
             let size = titleLabel.intrinsicContentSize
             let result = CGSize(width: size.width + contentEdgeInsets.horizontal + titleEdgeInsets.horizontal,
                                 height: size.height + contentEdgeInsets.vertical + titleEdgeInsets.vertical)
             return result
          } else {
             return super.intrinsicContentSize
          }
       }
    
       override open func layoutSubviews() {
          super.layoutSubviews()
          if let titleLabel = titleLabel, titleLabel.numberOfLines == 0, image == nil {
             let priority = UILayoutPriority.defaultLow + 1
             if titleLabel.horizontalContentHuggingPriority != priority {
                titleLabel.horizontalContentHuggingPriority = priority
             }
             if titleLabel.verticalContentHuggingPriority != priority {
                titleLabel.verticalContentHuggingPriority = priority
             }
             let rect = titleRect(forContentRect: contentRect(forBounds: bounds))
             titleLabel.preferredMaxLayoutWidth = rect.size.width
             super.layoutSubviews()
          }
       }
    }
    
    0 讨论(0)
  • 2020-12-03 13:51

    UPDATED Swift/Swift 2.0 version again based on @Jan's answer

    @IBDesignable
    class MultiLineButton:UIButton {
    
      //MARK: -
      //MARK: Setup
      func setup () {
        self.titleLabel?.numberOfLines = 0
    
        //The next two lines are essential in making sure autolayout sizes us correctly
        self.setContentHuggingPriority(UILayoutPriorityDefaultLow+1, forAxis: .Vertical) 
        self.setContentHuggingPriority(UILayoutPriorityDefaultLow+1, forAxis: .Horizontal)
      }
    
      //MARK:-
      //MARK: Method overrides
      required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
      }
    
      override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
      }
    
      override func intrinsicContentSize() -> CGSize {
        return self.titleLabel!.intrinsicContentSize()
      }
    
      override func layoutSubviews() {
        super.layoutSubviews()
        titleLabel?.preferredMaxLayoutWidth = self.titleLabel!.frame.size.width
      }
    }
    
    0 讨论(0)
  • 2020-12-03 13:52

    Lot of answers here, but the simple one by @Yevheniia Zelenska worked fine for me. Simplified Swift 5 version:

    @IBOutlet private weak var button: UIButton! {
        didSet {
            guard let titleHeightAnchor = button.titleLabel?.heightAnchor else { return }
            button.heightAnchor.constraint(equalTo: titleHeightAnchor).isActive = true
        }
    }
    
    0 讨论(0)
  • 2020-12-03 13:56

    This respects content edge insets and worked for me:

    class MultilineButton: UIButton {
    
        func setup() {
            self.titleLabel?.numberOfLines = 0
            self.setContentHuggingPriority(UILayoutPriorityDefaultLow + 1, for: .vertical)
            self.setContentHuggingPriority(UILayoutPriorityDefaultLow + 1, for: .horizontal)
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            setup()
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            setup()
        }
    
        override var intrinsicContentSize: CGSize {
            let size = self.titleLabel!.intrinsicContentSize
            return CGSize(width: size.width + contentEdgeInsets.left + contentEdgeInsets.right, height: size.height + contentEdgeInsets.top + contentEdgeInsets.bottom)
        }
    
        override func layoutSubviews() {
            super.layoutSubviews()
            titleLabel?.preferredMaxLayoutWidth = self.titleLabel!.frame.size.width
        }
    }
    
    0 讨论(0)
  • 2020-12-03 13:56

    Have you tried using this:

    self.leftButton.titleLabel.textAlignment = NSTextAlignmentCenter;
    self.leftButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail;
    self.leftButton.titleLabel.numberOfLines = 0;
    
    0 讨论(0)
提交回复
热议问题