使用嵌套的UISTackviews

时间:2017-03-17 01:47:23

标签: ios swift uiview uistackview

前言:我看了this post并没有解决我的问题。这是link to a repo,显示我遇到的错误。

我有一个UIViewController,其垂直UIStackView包含嵌套的水平UIStackViews

有两个UIStackViews被切换。如果显示UIStackViewNumber1,则隐藏UIStackViewNumber2&反之亦然。我最初将视图设置为显示两者,但它太拥挤了。

UIStackView
    stackViewThatDoesntMove
    stackViewNumber1
    stackViewNumber2
    stackViewThatDoesntMove

如果我不隐藏任何内容,一切正常,没有AutoLayout错误。每个UIStackViews都有嵌套的stackViews,其中包含按钮,标签,滑块等。我发现视图太拥挤了,所以我想我设置了一个stackViews并为变化设置动画,如下所示:

stackViewNumber2.isHidden = true

UIView.animate(withDuration: 0.33,
               options: [.curveEaseOut],
               animations: {
                self.stackViewNumber1.layoutIfNeeded()
                self.stackViewNumber2.layoutIfNeeded()
                self.view.layoutIfNeeded()
                    },
               completion: nil)
}

虽然我在Simulator和物理设备上获得了所需的结果,但是当我隐藏其中一个UIStackViews时,我的控制台就会出现AutoLayout错误。

我看了this post,我的问题似乎非常简单。我选择了最少的“簿记”方法并将stackViewNumber2包裹在UIView中。我最终遇到了一些错误,我没有将stackViewNumber1包裹在UIView中。

我还阅读Apple's documentation on UIStackView并尝试使用arrangeSubviews()来设置约束isActive = false,如下所示:

for subview in stackViewNumber2.arrangedSubviews {
    for constraint in subview.constraints {
        constraint.isActive = false
    }
}

stackViewNumber2.updateConstraints()
// then run animation block to update view

是否有更有效的方法隐藏嵌套UIStackViews而不添加IBOutlet约束,确保它不弱,并记录isActivetrue是否false / UIStackView

我认为我的问题与嵌套的stackViews有关,但我无法弄清楚如何解决它。感谢您阅读,我欢迎有关如何隐藏UIStackViews包含嵌套printf的建议。

2 个答案:

答案 0 :(得分:2)

而不是隐藏我认为删除stackView本身会更好。

myStackView.removeArrangedSubview(playButton)
playButton.removeFromSuperview()

希望它有所帮助。

答案 1 :(得分:1)

我开始希望动画隐藏一个视图并取消隐藏另一个视图,但在Md. Ibrahim Hassan's suggestion,我尝试从超视图中删除stackViewNumber1并将其替换为stackViewNumber2。最终的结果是更清晰,只需要最少的簿记,不会将大量@IBOutlets拖到viewController上以更新约束等。

parentStackView的视图按照arrangedSubviews()中显示的顺序存储在堆栈的Main.storyboard数组中。

enter image description here

在此示例中,arrangedSubviews数组如下所示:

[topStackView, stackViewNumber1, stackViewNumber2, stopButton]

我只需要了解parentStackViewstackViewNumber1stackViewNumber2,因此我将3个频道拖到故事板上,如下所示:

// StackViews the viewController needs to know about...
@IBOutlet weak var parentStackView: UIStackView!
// note weak is removed from the following 2 stackViews
@IBOutlet var stackViewNumber1: UIStackView!
@IBOutlet var stackViewNumber2: UIStackView!

从那里,如果我想删除stackViewNumber2,则以下代码将其删除:

parentStackView.removeArrangedSubview(stackViewNumber2)
// parentStackView.arrangedSubviews() = [topStackView, stackViewNumber1, stopButton]
stackViewNumber2.removeFromSuperview()
parentStackView.insertArrangedSubview(stackViewNumber1, at: 1)
// parentStackView.arrangedSubviews() = [topStackView, stackViewNumber1, stopButton]

现在,假设我要取出stackViewNumber1并将其替换为stackViewNumber2

parentStackView.removeArrangedSubview(stackViewNumber1)
// parentStackView.arrangedSubviews() = [topStackView, stopButton]
stackViewNumber2.removeFromSuperview()
parentStackView.insertArrangedSubview(stackViewNumber2, at: 1) 
// parentStackView.arrangedSubviews() = [topStackView, stackViewNumber2, stopButton]

召回stackViewNumber1stackViewNumber2不是weak。原因是我想保留它们所以我可以交换它们。由于将2 UIStackView出口更改为weak,我没有发现对内存使用产生任何负面影响。

最终结果:我的初始方法遇到的大量AutoLayout错误消失了,没有大量的簿记。

更新:

通过更多的修修补补,我也得到了动画效果。这是代码:

    UIView.animate(withDuration: 0.25,
                   delay: 0,
                   usingSpringWithDamping: 2.0,
                   initialSpringVelocity: 10.0,
                   options: [.curveEaseOut],
                   animations: {
                    self.view.layoutIfNeeded()
    },
                   completion: nil)