当前位置: 首页 > 知识库问答 >
问题:

设置活动时自动布局约束中断

郜昊苍
2023-03-14

我有一组AL约束来定位一个子vc,它有两个位置,展开和折叠。

我发现,当我添加折叠约束时,带有常量的上锚到下锚约束,当第一次创建vc时,当我激活它时,似乎有额外的间距。似乎是因为当时没有实际的高度。

当我在viewDidLayoutSubviews中添加约束时,额外的间距消失了,约束行为正常。除了现在在动画中的约束之间切换时,切换到展开约束和约束打断时,无法停用折叠的约束。可能是因为在整个过渡动画中调用viewDidLayoutSubviews。

下面是vc设置的摘要。

var foregroundExpandedConstraint: NSLayoutConstraint!
var foregroundCollapsedConstraint: NSLayoutConstraint!

var foregroundViewController: UIViewController? {
    didSet {

        setupforegroundViewController(foregroundViewController: foregroundViewController!)
    }
}

func setupforegroundViewController(foregroundViewController: UIViewController) {

    addChildViewController(foregroundViewController)
    foregroundViewController.didMove(toParentViewController: self)

    guard let foregroundView = foregroundViewController.view else { return }
    foregroundView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(foregroundView)

    foregroundExpandedConstraint = foregroundView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 15)

    let height =  view.safeAreaLayoutGuide.layoutFrame.height - 50 - 15
    let cellHeight = ((height) / 6)        
    foregroundCollapsedConstraint = NSLayoutConstraint(item: foregroundView, attribute: .top, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1, constant: (-cellHeight) * 2 - 50)

    let foregroundViewControllerViewConstraints = [
        foregroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        foregroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        foregroundView.heightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.heightAnchor, constant: -50 - 15),
        foregroundExpandedConstraint!
        ]


    NSLayoutConstraint.activate(foregroundViewControllerViewConstraints)
}

这里的动画是使用UIViewProperty tyAnimator预先形成的。

func animateTransitionIfNeeded(state: ForegroundState, duration: TimeInterval) {

    let containerFrameAnimator = UIViewPropertyAnimator(duration: duration, dampingRatio: 1) {
        [unowned self] in

        switch state {
        case .expanded:
            self.foregroundCollapsedConstraint?.isActive = false
            self.foregroundExpandedConstraint?.isActive = true
            self.view.layoutIfNeeded()
        case .collapsed:
            self.foregroundExpandedConstraint?.isActive = false
            self.foregroundCollapsedConstraint?.isActive = true
            self.view.layoutIfNeeded()
        }
    }

    containerFrameAnimator.addCompletion {  [weak self] (position) in

        if position == .start {
            switch state {
            case .collapsed:
                self?.foregroundCollapsedConstraint?.isActive = false
                self?.foregroundExpandedConstraint?.isActive = true
                self?.foregroundIsExpanded = true
                self?.view.layoutIfNeeded()
            case .expanded:
                self?.foregroundExpandedConstraint?.isActive = false
                self?.foregroundCollapsedConstraint?.isActive = true
                self?.foregroundIsExpanded = false
                self?.view.layoutIfNeeded()
            }
        } else if position == .end {
            switch state {
            case .collapsed:
                self?.foregroundExpandedConstraint?.isActive = false
                self?.foregroundCollapsedConstraint?.isActive = true
                self?.foregroundIsExpanded = false
            case .expanded:
                self?.foregroundExpandedConstraint?.isActive = false
                self?.foregroundCollapsedConstraint?.isActive = true
                self?.foregroundIsExpanded = true
            }
        }
        self?.runningAnimations.removeAll()
    }

再次重申,当我使用以下代码时,在vc添加到视图层次结构时设置约束,它不会正确布局。检查约束我看到它们在调用view Dod layout子视图后发生更改。除折叠的约束外,每个约束都会相应更改。

当我在视图did layout子视图中添加折叠的约束时,它的行为正常,但我无法继续停用它,约束会中断。

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let height =  view.safeAreaLayoutGuide.layoutFrame.height - 50 - 15
    let cellHeight = ((height) / 6)

    if let v = foregroundViewController?.view {
        foregroundCollapsedConstraint = NSLayoutConstraint(item: v, attribute: .top, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1, constant: (-cellHeight) * 2 - 50)
    }
}

编辑:我创建了一份回购协议,演示了该问题:https://github.com/louiss98/UIViewPropertyAnimator-Layout-Test

有什么建议吗?

共有1个答案

苏高远
2023-03-14

通过更改常量而不是创建新约束,可以消除“断开”约束。

viewdilayoutsubviews()中,

改变:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let height =  view.safeAreaLayoutGuide.layoutFrame.height - 50 - 15
    let cellHeight = ((height) / 6)

    foregroundCollapsedConstraint = NSLayoutConstraint(item: testViewController.view, attribute: .top, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1, constant: (-cellHeight) * 2 - 50)
}

收件人:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let height =  view.safeAreaLayoutGuide.layoutFrame.height - 50 - 15
    let cellHeight = ((height) / 6)

    foregroundCollapsedConstraint.constant = (-cellHeight) * 2 - 50
}

 类似资料:
  • 我在学习教程中的动画自动布局 http://weblog.invasivecode.com/post/42362079291/auto-layout-and-core-animation-auto-layout-was 一切都很顺利。 当我尝试在我的应用程序中使用这个概念,尝试从下到上设置设置屏幕(UIView)的动画时,当设置屏幕只是一个空的UIView时,效果非常好, 但如果我将UILabel

  • 许多有关自动布局约束动画的教程建议更新约束的常量属性,然后在动画块中调用。 我的处境有点棘手。我有一个包含3个子视图的视图。此超级视图的高度不是固定的-它是按其子视图的高度之和计算的。在某些情况下,我要求这3个子视图中的一个子视图切换其高度(它在0和30之间变化,即我希望平滑地隐藏和显示它)。代码类似于此: 不幸的是,这并不像我预期的那样有效。我可以看到子视图高度的平滑变化,但在为子视图高度约束设

  • 我花了两天时间尝试了混合和纯自动布局方法的各种解决方案,以实现在自动布局之前简单的滚动视图设置,现在它是正式的了——我一定太傻了。我主要是在故事板中设置这个(嗯,就是这样)。 所以我请求帮助。 视图树: 按钮应该水平滚动(从左到右,反之亦然)。有人能告诉我如何设置约束来使用纯自动布局实现这一点吗??? -- 我尝试了混合方法,如下所示: ...以及根据Apple的TechNote为< code>c

  • 我刚开始更彻底地使用AutoLayout,遇到了一个大问题: 我有一个视图,其中一些子视图附着在其顶部,一些子视图附着在其底部,因此当视图的高度发生变化时,子视图会相应地移动。根据用户的操作,子视图的高度可以更改(=其高度约束值更改),这可能会导致它们不再适合其父视图。 如何确定一组新的约束是否需要更改父视图的高度以适应其所有子视图?最好在我显示具有新约束的所有字段之前-我希望视图的高度同时改变。

  • 我注意到在iOS10 Beta 5(即将尝试Beta 6)中,AutoLayout约束动画的行为有点不同。 例如,此方法的工作原理与以前的iOS版本不同: 。。。在我的测试中,最初用添加约束(addConstraints)添加的约束也将在iOS 10中用UIView(UIView)来设置动画(animateWithDuration)(block)。。。到目前为止,这导致了一些古怪/不受欢迎的行为。

  • 我是AutoLayout的新手。我已经知道很多关于这个autoLayout的问题和教程,但是我还没有找到我的解决方案。所以提前感谢您的任何帮助。 我的要求是什么? 我必须制作UIView,它将在按下屏幕底部带有动画的按钮后出现在屏幕上。(如键盘)。我使用autoLayout在xib文件中创建了此UIView。到目前为止,我已经这样做了。 在ViewDidLoad中: 在这个视图中,它包含(滚动视图