我有一组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)
}
这里的动画是使用UIViewPropertyAnimator执行的。
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添加到视图层次结构中时设置约束,它的布局不正确。检查约束后,我看到它们在视图完成布局子视图后发生了变化。除折叠的约束外,每个约束都会适当地更改。
当我在视图的布局子视图中添加了折叠约束时,它的行为正常,但是我无法继续禁用它,并且约束中断。
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
有什么建议吗?
答案 0 :(得分:0)
您可以通过更改常量而不是创建新约束来消除“断开”约束。
在您的viewDidLayoutSubviews()
函数中,
更改:
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
}