Дети UIStackView равномерно распределены (вокруг и между)


Как у меня может быть UIStackView с тем же пространством, что и padding и gap между представлениями?

Как я могу добиться такой компоновки:

Ожидаемая планировка

Когда это мне не подходит:

Нет хорошей планировки

Так же как и это:

Введите описание изображения здесь

Мне просто нужно, чтобы пространство вокруг представлений было таким же, как пространство между представлениями. Почему это так трудно?

Важно Я использую свою вилку из TZStackView для поддержки iOS 7. Так что нет layoutMargins для меня : (

3 4

3 ответа:

Вы можете почти достичь того, что вы хотите, используя UIStackView. Когда вы сами устанавливаете некоторые ограничения на UIViews внутри UIStackView, вы можете придумать следующее:

Введите описание изображения здесь

Здесь отсутствует левая и правая обивка, которую вы ищете. Проблема в том, что UIStackView добавляет свои собственные ограничения, когда вы добавляете к нему представления. В этом случае вы можете добавить ограничения top и bottom, чтобы получить вертикальное заполнение, но при попытке добавить ограничение trailing для правое заполнение, UIStackView игнорирует или переопределяет это ограничение. Интересно, что добавление ограничения leading для левой прокладки работает.

Но устанавливать ограничения на UIStackView's упорядоченные подвиды-это не то, что вы хотите делать в любом случае. Весь смысл использования UIStackView состоит в том, чтобы просто дать ему некоторые представления и позволить UIStackView обрабатывать остальное. Добиться того, что вы пытаетесь сделать, на самом деле не так уж трудно. Вот пример UIViewController, который содержит пользовательский вид стека, который может обрабатывать заполнение со всех сторон (Я использовал SnapKit для ограничений):
import UIKit
import SnapKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let padding: CGFloat = 30

        let customStackView = UIView()
        customStackView.backgroundColor = UIColor(white: 0, alpha: 0.1)
        view.addSubview(customStackView)
        customStackView.snp_makeConstraints { (make) -> Void in
            make.top.left.equalTo(padding)
            make.right.equalTo(-padding)
        }

        // define an array of subviews
        let views = [UIView(), UIView(), UIView()]

        // UIView does not have an intrinsic contentSize
        // so you have to set some heights
        // In a real implementation the height will be determined
        // by the views' content, but for this example
        // you have to set the height programmatically
        views[0].snp_makeConstraints { (make) -> Void in
            make.height.equalTo(150)
        }
        views[1].snp_makeConstraints { (make) -> Void in
            make.height.equalTo(120)
        }
        views[2].snp_makeConstraints { (make) -> Void in
            make.height.equalTo(130)
        }

        // Iterate through the views and set the constraints
        var leftHandView: UIView? = nil
        for view in views {
            customStackView.addSubview(view)
            view.backgroundColor = UIColor(white: 0, alpha: 0.15)

            view.snp_makeConstraints(closure: { (make) -> Void in
                make.top.equalTo(padding)
                make.bottom.lessThanOrEqualTo(-padding)
                if let leftHandView = leftHandView {
                    make.left.equalTo(leftHandView.snp_right).offset(padding)
                    make.width.equalTo(leftHandView)
                } else {
                    make.left.equalTo(padding)
                }
                leftHandView = view
            })
        }

        if let lastView = views.last {
            lastView.snp_makeConstraints(closure: { (make) -> Void in
                make.right.equalTo(-padding)
            })
        }
    }
}
Это приводит к следующим результатам:

Введите описание изображения здесь

Я знаю, что это более старый вопрос, но способ, которым я решил его, состоял в том, чтобы добавить два UIView с нулевым размером в начале и конце моего стека, а затем использовать распределение .equalSpacing.

Примечание: это гарантирует только равное расстояние вокруг главной оси вида стека (то есть левый и правый края в моем примере)

let stack = UIStackView()

stack.axis         = .horizontal
stack.alignment    = .center
stack.distribution = .equalSpacing

// add content normally
// ...

// add extra views for spacing
stack.insertArrangedSubview(UIView(), at: 0)
stack.addArrangedSubview(UIView())

Введите описание изображения здесь

Для тех, кто продолжает приходить сюда в поисках решения этой проблемы. Я обнаружил, что лучшим способом (в моем случае) было бы использовать родительский UIView в качестве фона и отступа, например:

Введите описание изображения здесь

В этом случае UIStackView противопоставляется ребрам UIView с отступом и отделяет подвиды с интервалом.