【问题标题】:UIStackView children equally spaced (around and between)UIStackView 孩子等间距(周围和之间)
【发布时间】:2015-10-22 21:29:03
【问题描述】:

如何让 UIStackView 具有 与视图之间的填充和间隙相同的空间?

我怎样才能实现这种布局:

当这个不适合我时:

这也不行:

我只需要周围的视图空间与视图之间的空间相同。 为什么这么难?

重要 我使用my forkTZStackView 来支持iOS 7。所以我没有layoutMargins :(

【问题讨论】:

  • 您是使用故事板还是以编程方式工作?

标签: ios objective-c swift uistackview


【解决方案1】:

我知道这是一个较老的问题,但我解决它的方法是在堆栈的开头和结尾添加两个大小为零的 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())

【讨论】:

    【解决方案2】:

    您几乎可以使用 UIStackView 实现您想要的。当您自己在 UIStackView 内的 UIViews 上设置一些约束时,您可以提出以下建议:

    这缺少您正在寻找的左右填充。问题是UIStackView 在您向其添加视图时添加了自己的约束。在这种情况下,您可以添加 topbottom 约束以获得垂直填充,但是当您尝试为右侧填充添加 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)
                })
            }
        }
    }
    

    这会产生以下结果:

    【讨论】:

    • 您的回答非常好,非常感谢!但正如你所说,它错过了让 UIStackView 处理约束的重点=/
    • 确实如此,但您想要实现的目标是 UIStackView 无法实现的。没有像填充这样的东西,只有间距,但这只会影响视图之间的空间,而不是它们周围的空间
    【解决方案3】:

    对于那些一直在这里寻找解决此问题的方法的人。我发现(就我而言)最好的方法是使用父级 UIView 作为背景和填充,如下所示:

    在这种情况下,UIStackView 被限制在 UIView 的边缘,并带有填充,并用间距分隔子视图。

    【讨论】:

      猜你喜欢
      • 2017-08-20
      • 2016-04-26
      • 2019-05-25
      • 1970-01-01
      • 2013-04-30
      • 2017-05-20
      • 1970-01-01
      • 1970-01-01
      • 2016-07-14
      相关资源
      最近更新 更多