2
votes

How can I use snap kit to achieve the same spacing between views (and the superview for firstSubview.left and lastSubview.right) like for the bars in the picture below (and using SnapKit instead of stack view or so)?

enter image description here

Thanks!

1
Rather just use stackView? - Tj3n
As I wrote, is there an option with only snapkit and no stackview ? - Pascal
You can add each of them in a view then set their width equally, then it will do - Tj3n

1 Answers

7
votes

If you don't want to or cannot use a UIStackView you can achieve the same layout by setting centerX constraints to the superview and add different multipliers for each subview:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .gray

        let containerView = UIView()
        containerView.backgroundColor = .lightGray
        view.addSubview(containerView)

        let numberOfLines = 8
        for _ in 0..<numberOfLines {
            let lineView = UIView()
            lineView.backgroundColor = .cyan
            containerView.addSubview(lineView)
        }

        containerView.snp.makeConstraints { (make) in
            make.top.equalTo(60)
            make.left.equalTo(20)
            make.right.equalTo(-20)
            make.height.equalTo(150)
        }

        let centerXFactor: CGFloat = 2 / CGFloat(containerView.subviews.count + 1)
        containerView.subviews.enumerated().forEach { (index, lineView) in
            lineView.snp.makeConstraints({ (make) in
                make.top.bottom.equalTo(0)
                make.width.equalTo(4)
                make.centerX.equalTo(containerView).multipliedBy(CGFloat(index + 1) * centerXFactor)
            })
        }
    }
}

The only "magic" here is how to calculate the lineViews centerX multipliers: You know that when you have 8 lineViews you'll have 9 spaces inbetween them (also counting the spaces between the containerView's left and right edge and the first and last lineView).

To place a lineView's centerX on the right edge of the containerView, you would have to set its centerX constraint to the containerView's centerX constraint multiplied by 2 (You don't want to do that, but you need that value for the calculation).

Now, to get the multiplier for each lineView you divide 2 by the number of lineViews plus 1 (remember that we have one more space than we have lineViews). And then you set the centerX constraints on the lineViews as follows (for 8 lineViews the multiplier is 2 / 9 = 0.2222):

(pseudo code)
lineView 1: centerX = containerView.centerX multiplied by (1 * 0.2222)
lineView 2: centerX = containerView.centerX multiplied by (2 * 0.2222)
lineView 3: centerX = containerView.centerX multiplied by (3 * 0.2222)
etc.

Which gives you this:

enter image description here