iOS 11 UIStackView按比例填充会导致奇怪的视图加载动画

时间:2017-08-25 12:12:39

标签: ios swift uistackview ios11

如果我设置:

Sub AddCheckBoxesToArray()
    Dim chkAdQ As Variant
    Dim cb

    i = 0
    ReDim chkAdQ(i)
    For Each cb In Sheet2.OLEObjects
        If TypeName(cb.Object) = "CheckBox" Then
            If i > 0 Then ReDim Preserve chkAdQ(0 To i)
            Set chkAdQ(i) = cb
            i = i + 1
        End If
    Next cb

    For Each cb In chkAdQ
        Debug.Print cb.Name
    Next cb
End Sub

然后在iOS 11上,当加载包含此堆栈视图的视图时,我得到一个非常奇怪的动画(所有子视图 - 不仅仅是堆栈视图 - 从屏幕的顶部或底部飞行)。在较低的iOS版本上一切正常。如果我将堆栈视图的分布设置为其他任何东西,那么一切都可以正常工作。

有没有人知道造成这个问题的原因是什么?

谢谢。

3 个答案:

答案 0 :(得分:11)

我想我找到了一个解决方法 - 在self.view.layoutIfNeeded()区块中调用animations

这是我的复制品:

import UIKit

class ViewController: UIViewController {

    var showB = true

    weak var viewB: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let viewA = UIView()
        viewA.backgroundColor = UIColor.green

        let toggleViewBButtonAnimated = UIButton(frame: CGRect(x: 50, y: 150, width: 200, height: 40))
        toggleViewBButtonAnimated.backgroundColor = UIColor.cyan
        toggleViewBButtonAnimated.setTitle("Toggle B (animated)", for: .normal)
        viewA.addSubview(toggleViewBButtonAnimated)
        toggleViewBButtonAnimated.addTarget(self, action: #selector(toggleBButtonTappedAnimated), for: .touchUpInside)


        let viewB = UIView()
        viewB.backgroundColor = UIColor.orange
        let viewBHeightConstraint = viewB.heightAnchor.constraint(equalToConstant: 200)
        viewBHeightConstraint.priority = 999
        viewBHeightConstraint.isActive = true
        self.viewB = viewB


        let stackView = UIStackView(arrangedSubviews: [viewA, viewB])
        stackView.axis = .vertical
        stackView.alignment = .fill
        stackView.distribution = .fill
        stackView.translatesAutoresizingMaskIntoConstraints = false

        self.view.addSubview(stackView)

        stackView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        stackView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
        stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
    }

    @IBAction func toggleBButtonTappedAnimated() {
        self.showB = !self.showB
        UIView.animate(withDuration: 0.3,
                       animations: { self.viewB.isHidden = !self.showB; self.view.layoutIfNeeded() }
        )
    }
}

此控制器设置UIStackView,其中包含两个垂直视图,绿色视图(A)和橙色视图(B)。点击按钮隐藏/取消隐藏视图B.

如果self.view.layoutIfNeeded()块中有animations,那么,当显示视图B时,它会从屏幕顶部飞入。 (当视图B被隐藏时,它会正常隐藏 - 从屏幕底部向下移动。)

当我将self.view.layoutIfNeeded()添加到animations块时,视图B按预期显示 - 它从屏幕底部显示。

感谢来自@ g3rv4的回答,指出我朝这个方向发展!

答案 1 :(得分:1)

我今天早上使用转基因种子遇到了同样的问题。我最终使用UIView.performWithoutAnimation {块来进行任何UIStackView修改,暂时不需要动画。

答案 2 :(得分:1)

对我来说,问题是iOS 11中引入的行为回归,与UIStackView分发类型无关。我尝试了几个基于代码的解决方案无济于事:首先,在容器层次结构上调用layoutIfNeeded;其次,(如同一个类似问题的另一个答案所示)调整观点' contentMode。

我的hacky解决方案如下:

在UIStackView一侧添加一个新的零宽度UIView占位符,其中节目动画错误地从屏幕边缘引入了项目。