Aleksandr Maybach
Aleksandr Maybach

Reputation: 610

How correctly make constraints between view with intrinsic content size?

I have two UILabel(vertical direction) in UIView and UIButton in one "row". I need to get this result: enter image description here

Views init code:

private lazy var contentView: UIView = {
    let view = UIView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false

    return view
  }()

  private lazy var priceView: UIView = {
    let view = UIView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.setContentHuggingPriority(.required, for: .horizontal)

    return view
  }()

  private lazy var priceLabel: UILabel = {
    let label = UILabel(frame: .zero)
    label.numberOfLines = 1
    label.translatesAutoresizingMaskIntoConstraints = false

    return label
  }()

  private lazy var oldPriceLabel: UILabel = {
    let label = UILabel(frame: .zero)
    label.numberOfLines = 1
    label.translatesAutoresizingMaskIntoConstraints = false

    return label
  }()

  private lazy var callButton: UIButton = {
    let button = UIButton(frame: .zero)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.layer.cornerRadius = 22.0
    button.setTitleColor(.white, for: .normal)
    button.setTitle("Call", for: .normal)
    button.setContentHuggingPriority(.defaultLow, for: .horizontal)
    button.setContentCompressionResistancePriority(.required, for: .horizontal)

    return button
  }()

Using SnapKit I make constraints:

self.contentView.snp.makeConstraints { make in
  make.top.bottom.equalToSuperview()
  make.left.equalToSuperview().offset(16.0)
  make.right.equalToSuperview().offset(-16.0)
}
  self.priceView.snp.makeConstraints { make in
    make.centerY.left.equalToSuperview()
    make.right.equalTo(self.callButton.snp.left)

  }
  self.priceLabel.snp.makeConstraints { make in
    make.left.equalToSuperview()
    make.top.equalToSuperview()
    make.right.lessThanOrEqualToSuperview()
  }

  self.oldPriceLabel.snp.makeConstraints { make in
    make.left.bottom.equalToSuperview()
    make.top.equalTo(self.priceLabel.snp.bottom).offset(8.0)
    make.right.lessThanOrEqualToSuperview()
  })
  self.callButton.snp.makeConstraints { make in
   make.left.equalTo(self.priceView.snp.right)
    make.centerY.equalToSuperview()
    make.height.equalTo(44.0)
    make.right.equalToSuperview()

  }

I want priceView to shrink to the size of the UILabels and callButton stretch on all free space. Hugging and compression not working and I don't understand why.

Now: enter image description here

Upvotes: 0

Views: 1588

Answers (2)

DonMag
DonMag

Reputation: 77690

If you don't want to use a UIStackView, you can correct your issue easily...

For each label, change:

make.right.lessThanOrEqualToSuperview()

to:

make.right.equalToSuperview()

and that should fix it.

Upvotes: 1

Glenn Posadas
Glenn Posadas

Reputation: 13300

First off, you don't have to set translateAutoresizingMaskIntoConstraints to false in each of your views, since you're setting their constraints using SnapKit.

Next, the best way to deal with what you want is to utilize the purpose of UIStackView.

It's easy as this:

self.view.addSubview(self.stackView_Main)
self.stackView_Main.snp.makeConstraints { (make) in
    make.height.equalTo(44.0)
    make.leading.trailing.equalToSuperview().inset(16.0)
    make.top.equalToSuperview().inset(100.0)
}

self.callButton.snp.makeConstraints { (make) in
    make.top.bottom.equalToSuperview()
}

And you'll get this perfectly, no warnings:

enter image description here

Full example code:

import SnapKit
import UIKit

class ViewController: UIViewController {

    private lazy var stackView_Main: UIStackView = {
        let stackView = UIStackView(arrangedSubviews: [self.stackView_Price, self.callButton])
        stackView.axis = .horizontal
        stackView.spacing = 5.0
        stackView.alignment = .leading
        stackView.distribution = .fill
        return stackView
    }()

    private lazy var stackView_Price: UIStackView = {
        let stackView = UIStackView(arrangedSubviews: [self.priceLabel, self.oldPriceLabel])
        stackView.axis = .vertical
        stackView.spacing = 5.0
        return stackView
    }()

    private lazy var priceLabel: UILabel = {
        let label = UILabel(frame: .zero)
        label.numberOfLines = 1
        label.text = "500 000 000"
        return label
    }()

    private lazy var oldPriceLabel: UILabel = {
        let label = UILabel(frame: .zero)
        label.numberOfLines = 1
        label.text = "999 999 999 999"
        return label
    }()

    private lazy var callButton: UIButton = {
        let button = UIButton(frame: .zero)
        button.layer.cornerRadius = 22.0
        button.backgroundColor = .black
        button.setTitleColor(.white, for: .normal)
        button.setTitle("Call", for: .normal)
        button.setContentHuggingPriority(.defaultLow, for: .horizontal)
        button.setContentCompressionResistancePriority(.required, for: .horizontal)

        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()


        self.view.addSubview(self.stackView_Main)
        self.stackView_Main.snp.makeConstraints { (make) in
            make.height.equalTo(44.0)
            make.leading.trailing.equalToSuperview().inset(16.0)
            make.top.equalToSuperview().inset(100.0)
        }

        self.callButton.snp.makeConstraints { (make) in
            make.top.bottom.equalToSuperview()
        }
    }


}

Let me know if this helps ;)

Upvotes: 1

Related Questions