我有3个UIView图层的蛋糕,具有编程约束。
用于以编程方式设置约束的构造函数:
func setupViewConstraints(item:UIView, leadingTo:NSLayoutXAxisAnchor, leadingCon:CGFloat,
trailingTo:NSLayoutXAxisAnchor, trailingCon:CGFloat, topTo:NSLayoutYAxisAnchor,
topCon:CGFloat, bottomTo:NSLayoutYAxisAnchor, bottomCon:CGFloat) {
item.translatesAutoresizingMaskIntoConstraints = false
item.leadingAnchor.constraint(equalTo: leadingTo, constant: leadingCon).isActive = true
item.trailingAnchor.constraint(equalTo: trailingTo, constant: trailingCon).isActive = true
item.topAnchor.constraint(equalTo: topTo, constant:topCon).isActive = true
item.bottomAnchor.constraint(equalTo: bottomTo, constant:bottomCon).isActive = true
}
最低的基础层是lightGray。
view = UIView()
view.backgroundColor = .lightGray
第二层包含2个带有约束的UIView
(红色和蓝色)。
let red = UIView()
red.backgroundColor = .red
view.addSubview(red)
setupViewConstraints(item: red, leadingTo: view.leadingAnchor, leadingCon: 0, trailingTo: view.trailingAnchor, trailingCon: -(view.frame.width)*0.2), topTo: view.topAnchor, topCon: 0, bottomTo: view.bottomAnchor, bottomCon: -(view.frame.width)*0.8)
let blue = UIView()
blue.backgroundColor = .blue
view.addSubview(blue)
setupViewConstraints(item: blue, leadingTo: view.leadingAnchor, leadingCon: 0, trailingTo: view.trailingAnchor, trailingCon: -(view.frame.width)*0.2), topTo: red.bottomAnchor, topCon: 0, bottomTo: view.bottomAnchor, bottomCon: 0)
在顶部我有黄色UIView
层,它与所有较低层重叠。
let yellow = UIView()
yellow.backgroundColor = .yellow
view.addSubview(yellow)
setupViewConstraints(item: yellow, leadingTo: view.leadingAnchor, leadingCon: 0, trailingTo: view.trailingAnchor, trailingCon: 0, topTo: view.topAnchor, topCon: 0, bottomTo: view.bottomAnchor, bottomCon: 0)
此外,我在黄色UINavigationBar
内有UINavigationItem
UIView
。
//Add navigation item and buttons
naviItem = UINavigationItem()
naviItem.setRightBarButton(UIBarButtonItem(barButtonSystemItem:.add, target:self, action:#selector(goToDestVC)), animated: true)
naviItem.setLeftBarButton(UIBarButtonItem(image: UIImage(named: "hamburger_slim_30"), style: .plain, target: self, action: #selector(hamburgerBtnPressed)), animated: true)
//Add navigation bar with transparent background
naviBar = UINavigationBar()
naviBar.setBackgroundImage(UIImage(), for: .default)
naviBar.shadowImage = UIImage()
naviBar.isTranslucent = true
// Assign the navigation item to the navigation bar
naviBar.items = [naviItem]
view.addSubview(naviBar)
setupViewConstraints(item: naviBar, leadingTo: yellow.leadingAnchor, leadingCon: 0, trailingTo: yellow.trailingAnchor, trailingCon: 0, topTo: yellow.topAnchor, topCon: 0, bottomTo: yellow.bottomAnchor, bottomCon: -(view.frame.height)*0.9))
我有hamburgerBtnPressed
函数,它应该将黄色图层向右移动80%(我将前导和尾随常量的值改为80%),但这不起作用!! !
var hamburgerMenuIsVisible = false
@objc func hamburgerBtnPressed(_ sender: Any) {
if !hamburgerMenuIsVisible {
let menuWidth = (self.view.frame.width)*0.8
setupViewConstraints(item: layoutView, leadingTo: view.leadingAnchor, leadingCon: menuWidth, trailingTo: view.trailingAnchor, trailingCon: menuWidth, topTo: view.topAnchor, topCon: 0, bottomTo: view.bottomAnchor, bottomCon: 0)
hamburgerMenuIsVisible = true
} else {
setupViewConstraints(item: layoutView, leadingTo: view.leadingAnchor, leadingCon: 0, trailingTo: view.trailingAnchor, trailingCon: 0, topTo: view.topAnchor, topCon: 0, bottomTo: view.bottomAnchor, bottomCon: 0)
hamburgerMenuIsVisible = false
}
// layoutIfNeeded() lays out the subviews immediately and forces the layout before drawing
UIView.animate(withDuration: 0.2, delay:0.0, options: .curveEaseIn, animations: {
self.view.layoutIfNeeded()
}) { (animationComplete) in
print("Animation is complete!")
}
}
但如果我将前导和尾随常量的值更改为负数,一切都会起作用,菜单会向左移动而没有任何问题。
let menuWidth = -(self.view.frame.width)*0.8
请解释一下......问题是什么?为什么黄色UIView
向左移动了约束的负值,并且不能与约束的正值一起使用?并给出错误:
Probably at least one of the constraints in the following list is one you don't want.
(
"<NSLayoutConstraint:0x6040002853c0 UIView:0x7fa947c35850.trailing == UIView:0x7fa947e1d2d0.trailing (active)>",
"<NSLayoutConstraint:0x604000092750 UIView:0x7fa947c35850.trailing == UIView:0x7fa947e1d2d0.trailing + 331.2 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x604000092750 UIView:0x7fa947c35850.trailing == UIView:0x7fa947e1d2d0.trailing + 331.2 (active)>
更新:我选择选项2 : 保持对要更改的约束的引用,并调整其常量。在layoutIfNeeded之前也需要调用setNeedsLayout。
更新的代码:
var leadingC: NSLayoutConstraint!
var trailingC: NSLayoutConstraint!
var yellow: UIView!
的loadView():
yellow = UIView()
yellow.backgroundColor = .yellow
view.addSubview(yellow)
//Set up leading and trailing constraints for handling yellow view shift
leadingC = yellow.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0)
trailingC = yellow.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0)
//Put leadingC.constant and trailingC.constant into the function
setupViewConstraints(item: yellow, leadingTo: view.leadingAnchor, leadingCon: leadingC!.constant, trailingTo: view.trailingAnchor, trailingCon: trailingC.constant, topTo: view.topAnchor, topCon: 0, bottomTo: view.bottomAnchor, bottomCon: 0)
更新了汉堡功能:
@objc func hamburgerBtnPressed(_ sender: Any) {
if !hamburgerMenuIsVisible {
let menuWidth = (self.view.frame.width)*0.8
leadingC!.constant = menuWidth
trailingC!.constant = menuWidth
print(leadingC.constant, trailingC.constant)
hamburgerMenuIsVisible = true
} else {
leadingC!.constant = 0
trailingC!.constant = 0
hamburgerMenuIsVisible = false
}
// layoutIfNeeded() lays out the subviews immediately and forces the layout before drawing
UIView.animate(withDuration: 0.2, delay:0.0, options: .curveEaseIn, animations: {
self.view.setNeedsLayout()
self.view.layoutIfNeeded()
}) { (animationComplete) in
print("Animation is complete!")
}
}
var hamburgerMenuIsVisible = false
我没有错误,&#34;动画完成!&#34;也打印过,但屏幕上没有任何反应,没有动画。
答案 0 :(得分:1)
首先,它需要负值,因为需要在正确的方向上设置约束。更改此设置,您可以删除所有这些负常量:
//myDbBinary
let
Source = Binary.Buffer(File.Contents(DataFolder_param & FileName_param),
[CreateNavigationProperties=true]))
in
Source
// Table1 Query
let
Source = Access.Database(myDbBinary, [CreateNavigationProperties=true]),
_Table1 = Source{[Schema="",Item="Table1"]}[Data]
in
_Table1
到
item.leadingAnchor.constraint(equalTo: leadingTo, constant: leadingCon).isActive = true
item.trailingAnchor.constraint(equalTo: trailingTo, constant: trailingCon).isActive = true
item.topAnchor.constraint(equalTo: topTo, constant:topCon).isActive = true
item.bottomAnchor.constraint(equalTo: bottomTo, constant:bottomCon).isActive = true
其次,每次调用item.leadingAnchor.constraint(equalTo: leadingTo, constant: leadingCon).isActive = true
trailingTo.constraint(equalTo: item.trailingAnchor, constant: trailingCon).isActive = true
item.topAnchor.constraint(equalTo: topTo, constant:topCon).isActive = true
bottomTo.constraint(equalTo: item.bottomAnchor, constant:bottomCon).isActive = true
时,您都在创建并激活另一组约束。
选项1:
在重新设置之前删除黄色视图的所有约束。
选项2:
保持对要更改的约束的引用,并调整其常量。您可能需要在setupViewConstraints
之前致电setNeedsLayout
。
选项3:
添加2个约束。最初的主要约束,以及您想要的宽度。当您要显示/隐藏菜单时,将第一个约束的优先级更改为layoutIfNeeded
(默认为999
)并切换另一个约束的1000
属性。
isActive
选项2可能是性能最佳的选项。来自apple docs:
在现有约束上设置常量会更好 而不是删除约束并添加一个新的约束 旧的除了它有不同的常数