我已经在https://github.com/rDivaDuck/TestAppError
上创建了该问题的最小工作示例。我的HomeController是一个UICollectioviewController,我有一个设置启动器类,我试图在导航栏中的按钮按下时从底部向上进行动画处理,我已经通过禁用向下约束并激活了向上约束来实现此目的。然后调用window.layoutifneeded()为更改设置动画。但是,我仍然抛出一个典型的约束冲突错误,即向下约束仍然处于活动状态。
我可以使用.frame并为CGRect更改设置动画效果,但是我想使用自动布局获得相同的效果。
class SettingsLauncher {
var homeController: HomeController?
let shadowView = UIView()
let MenuView: UIView = {
let View = UIView(frame: .zero)
View.backgroundColor = UIColor.white
View.translatesAutoresizingMaskIntoConstraints = false
return View
}()
var downConstraint: NSLayoutConstraint?
var upConstraint: NSLayoutConstraint?
func showSettings() {
if let window = UIApplication.shared.keyWindow{
shadowView.backgroundColor = UIColor(white: 0,
alpha: 0.4)
shadowView.addGestureRecognizer(UITapGestureRecognizer(target: self,
action: #selector(settingsDown)))
window.addSubview(shadowView)
shadowView.frame = window.frame
shadowView.alpha = 0
window.addSubview(MenuView)
downConstraint = MenuView.topAnchor.constraint(equalTo: window.bottomAnchor)
downConstraint?.isActive = true
upConstraint = MenuView.topAnchor.constraint(equalTo: window.bottomAnchor, constant: -300)
MenuView.heightAnchor.constraint(equalToConstant: 300).isActive = true
MenuView.leadingAnchor.constraint(equalTo: window.leadingAnchor).isActive = true
MenuView.trailingAnchor.constraint(equalTo: window.trailingAnchor).isActive = true
MenuView.layoutIfNeeded()
window.layoutIfNeeded()
settingsUp()
}
}
func settingsUp() {
downConstraint?.isActive = false
upConstraint?.isActive = true
UIView.animate(withDuration: 0.5,
delay: 0,
usingSpringWithDamping: 1,
initialSpringVelocity: 1,
options: .curveEaseOut,
animations: {
self.shadowView.alpha = 1
if let window = UIApplication.shared.keyWindow {
window.layoutIfNeeded()
}
}, completion: nil)
}
@objc func settingsDown() {
downConstraint?.isActive = true
upConstraint?.isActive = false
UIView.animate(withDuration: 0.5,
animations: {
self.shadowView.alpha = 0
if let window = UIApplication.shared.keyWindow {
window.layoutIfNeeded()
}
}, completion: nil )
}
}
(
"<NSLayoutConstraint:0x600001b5e440 V:[UIWindow:0x7fde18514030]-(-300)-[UIView:0x7fde18525ea0] (active)>",
"<NSLayoutConstraint:0x600001b5f250 V:[UIWindow:0x7fde18514030]-(0)-[UIView:0x7fde18525ea0] (active)>"
)
我该如何解决?
答案 0 :(得分:0)
您好,欢迎来到StackOverflow,您的项目中存在多个错误。主要问题在于,每次您点击按钮并调用showSettings()
时,您向MenuView添加的新约束都与先前的约束冲突,因此要解决此问题,您应该只执行一次代码的约束部分:
var viewInitialized = false
func showSettings() {
if let window = UIApplication.shared.keyWindow {
if !viewInitialized {
viewInitialized = true
shadowView.backgroundColor = UIColor(white: 0, alpha: 0.4)
shadowView.addGestureRecognizer(UITapGestureRecognizer(target: self,
action: #selector(settingsDown)))
window.addSubview(shadowView)
shadowView.frame = window.frame
shadowView.alpha = 0
window.addSubview(MenuView)
downConstraint = MenuView.topAnchor.constraint(equalTo: window.bottomAnchor)
downConstraint?.isActive = true
upConstraint = MenuView.topAnchor.constraint(equalTo: window.bottomAnchor, constant: -300)
MenuView.heightAnchor.constraint(equalToConstant: 300).isActive = true
MenuView.leadingAnchor.constraint(equalTo: window.leadingAnchor).isActive = true
MenuView.trailingAnchor.constraint(equalTo: window.trailingAnchor).isActive = true
MenuView.layoutIfNeeded()
window.layoutIfNeeded()
}
settingsUp()
}
}
还可以在settingsDown()
中切换激活语句,以便您在激活另一个约束之前先取消激活约束,有时会引起警告。
@objc func settingsDown() {
upConstraint?.isActive = false
downConstraint?.isActive = true
...
我发现的项目的其他问题:
AppDelegate.swift
中创建一个新窗口?已经有一个,您可以使用它。只需删除无用的window = UIWindow(frame: UIScreen.main.bounds)
AppDelegate.swift
中创建导航控制器?将其添加到情节提要中作为第一个视图控制器。 HomeController
的相同操作是将一个CollectionViewController添加到情节提要,并将其类更改为HomeController
SettingsLauncher.swift
shadowView
中缺少约束