Multiline UIButton and autolayout

后端 未结 16 1453
无人共我
无人共我 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:57

    A simple solution working for me: make the multiline button to respect its title height in Swift 4.2 by adding a constraint for the button's height based on its title label's height:

    let height = NSLayoutConstraint(item: multilineButton,
                                   attribute: .height,
                                   relatedBy: .equal,
                                   toItem: multilineButton.titleLabel,
                                   attribute: .height,
                                   multiplier: 1,
                                   constant: 0)
    multilineButton.addConstraint(height)
    
    0 讨论(0)
  • 2020-12-03 13:58

    @Jan's answer doesn't work for me in (at least) iOS 8.1, 9.0 with Xcode 9.1. The problem: titleLabel's -intrinsicContentSize returns very big width and small height as there is no width limit at all (titleLabel.frame on call has zero size that leads to measurements problem). Moreover, it doesn't take into account possible insets and/or image.

    So, here is my implementation that should fix all the stuff (only one method is really necessary):

    @implementation PRButton
    
    - (CGSize)intrinsicContentSize
    {
        CGRect titleFrameMax = UIEdgeInsetsInsetRect(UIEdgeInsetsInsetRect(UIEdgeInsetsInsetRect(
            self.bounds, self.alignmentRectInsets), self.contentEdgeInsets), self.titleEdgeInsets
        );
        CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(titleFrameMax.size.width, CGFLOAT_MAX)];
    
        CGSize superSize = [super intrinsicContentSize];
        return CGSizeMake(
            titleSize.width + (self.bounds.size.width - titleFrameMax.size.width),
            MAX(superSize.height, titleSize.height + (self.bounds.size.height - titleFrameMax.size.height))
        );
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-03 14:04

    Swift 4.1.2 Version based on @Jan answer.

    import UIKit
    
    class MultiLineButton: UIButton {
    
        // MARK: - Init
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
    
            self.commonInit()
        }
    
        private func commonInit() {
            self.titleLabel?.numberOfLines = 0
            self.titleLabel?.lineBreakMode = .byWordWrapping
        }
    
        // MARK: - Overrides
    
        override var intrinsicContentSize: CGSize {
            get {
                 return titleLabel?.intrinsicContentSize ?? CGSize.zero
            }
        }
    
        override func layoutSubviews() {
            super.layoutSubviews()
            titleLabel?.preferredMaxLayoutWidth = titleLabel?.frame.size.width ?? 0
            super.layoutSubviews()
        }
    
    }
    
    0 讨论(0)
  • 2020-12-03 14:06

    I had the same problem where I wanted my button to grow along with its title. I had to sublcass the UIButton and its intrinsicContentSize so that it returns the intrinsic size of the label.

    - (CGSize)intrinsicContentSize
    {
        return self.titleLabel.intrinsicContentSize;
    }
    

    Since the UILabel is multiline, its intrinsicContentSize is unknown and you have to set its preferredMaxLayoutWidth See objc.io article about that

    - (void)layoutSubviews
    {
        [super layoutSubviews];
        self.titleLabel.preferredMaxLayoutWidth = self.titleLabel.frame.size.width;
        [super layoutSubviews];
    }
    

    The rest of the layout should work. If you set your both button having equal heights, the other one will grow to. The complete button looks like this

    @implementation TAButton
    
    - (instancetype)initWithCoder:(NSCoder *)coder
    {
        self = [super initWithCoder:coder];
        if (self) {
            self.titleLabel.numberOfLines = 0;
            self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
        }
        return self;
    }
    
    - (CGSize)intrinsicContentSize
    {
        return self.titleLabel.intrinsicContentSize;
    }
    
    - (void)layoutSubviews
    {
        [super layoutSubviews];
        self.titleLabel.preferredMaxLayoutWidth = self.titleLabel.frame.size.width;
        [super layoutSubviews];
    }
    
    @end
    
    0 讨论(0)
提交回复
热议问题