gpt4 book ai didi

ios - 以编程方式越界 UIView 约束

转载 作者:行者123 更新时间:2023-11-28 15:12:05 25 4
gpt4 key购买 nike

我有一个由 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
}

最低的基础层是浅灰色。

view = UIView()
view.backgroundColor = .lightGray

第 2 层包含 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)

3 UIView

在顶部我有黄色的 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)

此外,我在黄色 UIView 中有 UINavigationBarUINavigationItem

//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))

Top UIView layer with UINavigationBar

而且我有 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

To the left

请解释.. 问题是什么?为什么黄色的 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!

加载 View ():

    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)

更新的 Hamburger 函数:

 @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

我没有错误和“动画完成!”也被打印出来了,但是屏幕上没有任何反应,没有动画。

Output

最佳答案

首先,它需要负值,因为需要在正确的方向上设置约束。改变这个,你可以删除所有这些负常量:

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

其次,每次调用 setupViewConstraints 时,您都在创建并激活另一组约束。

选项 1:

在重新设置之前移除黄色 View 的所有约束。

选项 2:

保留对要更改的约束的引用,并仅调整其常量。您可能还需要在 layoutIfNeeded 之前调用 setNeedsLayout

选项 3:

添加 2 个约束。初始前导约束,以及您想要的宽度。将第一个约束的优先级更改为 999(默认为 1000)并在要显示/隐藏时切换另一个约束的 isActive 属性菜单。

let leading = yellow.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0)
leading.priority = UILayoutPriority(999)
leading.isActive = true

let otherConstraint = yellow.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: (view.frame.width)*0.8)
otherConstraint.isActive = false // toggle this property to show/hide

选项 2 可能是性能最好的。来自苹果文档:

Setting the constant on an existing constraint performs much better than removing the constraint and adding a new one that's exactly like the old except that it has a different constant

关于ios - 以编程方式越界 UIView 约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47469954/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com