1

I am having a little issue with the frame of a button. The screenshot below shows the situation. There are two buttons, one with a short title (the 1st) and one with a long title extending on 2 lines (the 2nd).

For each button I set up a view (with a shaded color). It is meant to mach the size of the button but as one can see it does not work.

enter image description here

Here is the code I use to create the view and try to match the frame of the view to that of its associated button. Can anyone see why it is not working. It seems like the button frame is careless of the title inside. Is that the way it is supposed to be?

for button in [firstButn,secondButn] {
    button.setTitleColor(UIColor.darkGray, for: .normal)
    let bgView = UIView()
    bgView.backgroundColor = UIColor.black.withAlphaComponent(0.17)
    bgView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(bgView)
    view.addConstraints([
        NSLayoutConstraint(item: bgView, attribute: .leading, relatedBy: .equal,
                           toItem: button, attribute: .leading,
                           multiplier: 1.0, constant: 0.0),
        NSLayoutConstraint(item: bgView, attribute: .trailing, relatedBy: .equal,
                           toItem: button, attribute: .trailing,
                           multiplier: 1.0, constant: 0.0),
        NSLayoutConstraint(item: bgView, attribute: .top, relatedBy: .equal,
                           toItem: button, attribute: .top,
                           multiplier: 1.0, constant: 0.0),
        NSLayoutConstraint(item: bgView, attribute: .bottom, relatedBy: .equal,
                           toItem: button, attribute: .bottom,
                           multiplier: 1.0, constant: 0.0)])
}

Here are the constraints on the buttons:

for button in [firstButn,secondButn] {
    view.addConstraints([
        NSLayoutConstraint(item: button, attribute: .centerX, relatedBy: .equal,
                           toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0.0),
        NSLayoutConstraint(item: button, attribute: .width, relatedBy: .equal,
                           toItem: view, attribute: .width, multiplier: 0.6, constant: 0.0)])
}

view.addConstraints([
    NSLayoutConstraint(item: firstButn, attribute: .centerY, relatedBy: .equal,
                       toItem: view, attribute: .centerY, multiplier: 2.0/5.0, constant: 0.0),
    NSLayoutConstraint(item: secondButn, attribute: .centerY, relatedBy: .equal,
                       toItem: view, attribute: .centerY, multiplier: 4.0/5.0, constant: 0.0)])

As on can see, nothing is imposed on the height.

Michel
  • 10,303
  • 17
  • 82
  • 179

2 Answers2

1

Replace

view.addConstraints([
    NSLayoutConstraint(item: bgView, attribute: .leading, relatedBy: .equal,
                       toItem: button, attribute: .leading,
                       multiplier: 1.0, constant: 0.0),
    NSLayoutConstraint(item: bgView, attribute: .trailing, relatedBy: .equal,
                       toItem: button, attribute: .trailing,
                       multiplier: 1.0, constant: 0.0),
    NSLayoutConstraint(item: bgView, attribute: .top, relatedBy: .equal,
                       toItem: button, attribute: .top,
                       multiplier: 1.0, constant: 0.0),
    NSLayoutConstraint(item: bgView, attribute: .bottom, relatedBy: .equal,
                       toItem: button, attribute: .bottom,
                       multiplier: 1.0, constant: 0.0)])

with

view.addConstraints([
    NSLayoutConstraint(item: bgView, attribute: .leading, relatedBy: .equal,
                       toItem: button, attribute: .leading,
                       multiplier: 1.0, constant: 0.0),
    NSLayoutConstraint(item: bgView, attribute: .trailing, relatedBy: .equal,
                       toItem: button, attribute: .trailing,
                       multiplier: 1.0, constant: 0.0),
    NSLayoutConstraint(item: bgView, attribute: .top, relatedBy: .equal,
                       toItem: button.titleLabel, attribute: .top,
                       multiplier: 1.0, constant: 0.0),
    NSLayoutConstraint(item: bgView, attribute: .bottom, relatedBy: .equal,
                       toItem: button.titleLabel, attribute: .bottom,
                       multiplier: 1.0, constant: 0.0)])

You will see something like that (iPod touch 6, iOS 12.4):

Running on iPod touch 6

Roman Podymov
  • 4,168
  • 4
  • 30
  • 57
  • 1
    Yes, it works. Since there is nothing on the buttons but the labels, I think this should come as the default behavior. But anyway thanks! – Michel Jul 24 '19 at 09:20
0

You can tweak titleEdgeInsets property of UIButton - the text size will automatically adjust accordingly.

For example:

.titleEdgeInsets = UIEdgeInsets(10,10,10,10)

Above will make +10 points margin from each of the four sides for the button title.

Also, there should not be any need to add bgView just for the sake of background color. Use backGroundColor property of UIButton.

Nirav Bhatt
  • 6,940
  • 5
  • 45
  • 89
  • where are you setting the titletext? – Nirav Bhatt Jul 24 '19 at 08:41
  • In a function called from viewDidLoad(). – Michel Jul 24 '19 at 08:49
  • Frames reflect their values at later stage i.e. in viewWilllayoutsubviews or viewWillAppar. – Nirav Bhatt Jul 24 '19 at 13:57
  • However, your current code (and accepted answer) is quite absurd approach - all you want is highlighting the text of a button - creating a view for it along with constraints to UIButton's child view is an overkill idea (and a stupid one) - completely not the correct use of the API. You could have used setAttributedTitle along with NSBackgroundColorAttributeName property to color the background just for the text. Use titleEdgeInsets for resizing. – Nirav Bhatt Jul 24 '19 at 13:58
  • All you write may be true but the fact is what I had before was not working and what I have now is working. Another (maybe better) approach is not excluded indeed. I had also tempted to act later (in viewWillAppar) but that also did not work. I did not try setAttributedTitle. – Michel Jul 26 '19 at 07:35