堆栈视图 - 但具有“比例”间隙

时间:2018-01-31 16:44:35

标签: ios autolayout uistackview

想象一下包含四个项目的堆栈视图,填充一些内容。 (说,填写屏幕)。

请注意,三个缺口,ABC。

enter image description here

(注意 - 黄色块总是各自固定的高度。)

(只有间隙会发生变化,具体取决于堆栈视图可用的总高度。)

说UISV能够绘制所有内容,比如剩下300个。这三个差距各为100个。

在这个例子中,剩下9个,所以A B和C各为3个。

然而

通常,您希望间隙本身享受比例关系

因此 - 您的设计师可能会说类似

  

如果屏幕太高,请展开A,B和C处的空格。总是扩大B,比A和B的间隙快4倍。“

所以,如果留下“12”,那将是2,8,2。而当剩下18时,那将是3,12,3。

这个概念在堆栈视图中是否可用?否则,你会怎么做?

(注意,最近添加到堆栈视图中,您确实可以单独指定间隙。因此,可以“手动”执行此操作,但这将是一个真正的混乱,您将与解算器一起工作很多。)

3 个答案:

答案 0 :(得分:4)

您可以通过以下解决方法来实现这一目标。而不是间距,为每个空间添加一个新的UIView(),它将是一个可伸缩的空间。然后只需在这些"空格"的高度之间添加约束。这会根据你想要的乘数将它们的高度限制在一起,例如:

space1.heightAnchor.constraint(equalTo: space2.heightAnchor, multiplier: 2).isActive = true

为了使其工作,我认为你必须添加一个约束,试图在有空位的情况下拉伸这些空间:

let stretchingConstraint = space1.heightAnchor.constraint(equalToConstant: 1000)
// lowest priority to make sure it wont override any of the rest of constraints and compression resistances
stretchingConstraint.priority = UILayoutPriority(rawValue: 1)
stretchingConstraint.isActive = true

"正常"内容视图必须具有内在大小或显式约束,以便将其高度设置为正常工作。

以下是一个例子:

class MyViewController: UIViewController {

    fileprivate let stack = UIStackView()

    fileprivate let views = [UIView(), UIView(), UIView(), UIView()]
    fileprivate let spaces = [UIView(), UIView(), UIView()]

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = .white

        self.view.addSubview(stack)

        // let stack fill the whole view
        stack.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            stack.topAnchor.constraint(equalTo: self.view.topAnchor),
            stack.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
            stack.leftAnchor.constraint(equalTo: self.view.leftAnchor),
            stack.rightAnchor.constraint(equalTo: self.view.rightAnchor),
            ])

        stack.alignment = .fill
        // distribution must be .fill
        stack.distribution = .fill
        stack.spacing = 0
        stack.axis = .vertical

        for (index, view) in views.enumerated() {
            stack.addArrangedSubview(view)
            view.translatesAutoresizingMaskIntoConstraints = false
            // give it explicit height (or use intrinsic height)
            view.heightAnchor.constraint(equalToConstant: 50).isActive = true

            view.backgroundColor = .orange

            // intertwin it with spaces
            if index < spaces.count {
                stack.addArrangedSubview(spaces[index])
                spaces[index].translatesAutoresizingMaskIntoConstraints = false
            }
        }
        // constraints for 1 4 1 proportions
        NSLayoutConstraint.activate([
            spaces[1].heightAnchor.constraint(equalTo: spaces[0].heightAnchor, multiplier: 4),
            spaces[2].heightAnchor.constraint(equalTo: spaces[0].heightAnchor, multiplier: 1),
            ])

        let stretchConstraint = spaces[0].heightAnchor.constraint(equalToConstant: 1000)
        stretchConstraint.priority = UILayoutPriority(rawValue: 1)
        stretchConstraint.isActive = true
    }
}

答案 1 :(得分:2)

值得注意的是,@MilanNosáľ的解决方案非常有效。

您无需设置任何优先级/等等 - 它在iOS求解器中“自然地”完美运行!

enter image description here

将四个内容区域简单地设置为50个固定高度。 (使用任何内在内容项。)

根本不要设置“gap1”的高度。

将gap2和gap3设置为gap1的相等高度。

enter image description here

只需 - 为gap2和gap3设置所需的比率!

与间隙1对比。

因此,gap2为gap1的高度为0.512,gap3为gap1的高度为0.398等。

它确实解决了所有情况。

奇!!!!!!!!!!

所以:三个例子中的 (具有三种不同屏幕高度的手机)。 实际上差距的相对高度总是一样的。你的设计部门会高兴! :)

答案 2 :(得分:1)

已创建:a gist with a storyboard example

此处的关键是您排列的视图与参考视图之间的Equal Heightsenter image description here 然后将“乘数”更改为所需的大小: Full example with constraints

在这个例子中,主视图大小为0.2(深灰色),对中为0.05(黑色),对之间为0.1(浅灰色)

然后只需更改包含视图的大小将导致视图按比例重新调整大小:

Changed Size

这完全在故事板中,但你可以在代码中做同样的事情。

请注意,我只使用StackView中的比例来避免总大小不正确(并确保它们加起来为1.0),但也应该有一些设定的高度如果正确完成,则在StackView内。