Ich habe einen Kuchen von 3 UIView-Ebenen mit programmatischen Einschränkungen.Out-of-Grenzen UIView Constraints programmgesteuert
Funktion Konstruiert für programm eingerichtet Constraints:
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
}
Die unterste Basisschicht ist hellgrau.
view = UIView()
view.backgroundColor = .lightGray
Die 2. Schicht enthält 2 UIView
(rot und blau) mit Einschränkungen.
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)
Und oben Ich habe gelbe UIView
Schicht, die alle unteren Schichten überlappt.
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)
Auch habe ich UINavigationBar
mit UINavigationItem
innerhalb des gelben 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))
Und ich habe hamburgerBtnPressed
Funktion, die die gelbe Schicht nach rechts um 80% verschieben sollte (ich die Werte der führenden ändern und Konstanten um 80% nachgestellt), aber dies nicht Arbeit!!!
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!")
}
}
Aber wenn ich die Werte der Vorder- und die Hinter Konstanten negativ ändern, wird alles funktionieren, und das Menü wird ohne Probleme nach links verschieben.
let menuWidth = -(self.view.frame.width)*0.8
Bitte erläutern .. was das Problem ist? Warum ist die gelbe UIView
nach links mit negativen Werten von Constraints verschoben und arbeitet nicht mit positiven Werten von Constraints? und gibt einen Fehler:
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)>
Update: ich wählen haben Option 2: Halten Sie einen Verweis auf die Einschränkung, die Sie ändern wollen, und nur seine konstant einzustellen. Sie müssen setNeedsLayout auch vor layoutIfNeeded aufrufen.
Aktualisiert Code:
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)
Aktualisiert Hamburger Funktion: "Animation, complete"
@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
Ich habe keine Fehler und wurde auch gedruckt, aber nichts passiert auf dem Bildschirm, keine Animation.
Dies ist ein Grund, persönlich ich * nicht * Einschränkung Schöpfung in eine generische Funktion kombinieren - zu schwer zu entziffern. Erstens, wenn ich dich richtig gelesen habe, gibt es * kein * Problem mit roten, blauen und grauen Ansichten, richtig? Wenn ja, bitte entfernen Sie sie von Ihrer Frage, da es für Lärm sorgt. Versuchen Sie, 80% eines Frames zu berechnen, um (a) zu verschieben oder (b) die gelbe Ansicht zu verkleinern? Denn im ersten Fall haben Sie bereits gesagt, dass es funktioniert - weil Sie führende/nachlaufende Anker bewegen. Aber wenn Sie Letzteres wollen, müssen Sie den Breiten-Anker ändern - was ich in Ihrer generischen Funktion nicht sehe. – dfd
Ich möchte die gelbe UIView um 80% nach rechts verschieben, um (a) die gelbe Ansicht zu verschieben. Ich verwende Trailing-Anker für "Breite", und ich kann nur Breite OR Trailing-Anker setzen, sonst um Konflikte zu bekommen. – Rurom
Korrigieren. Es klingt also nach einer * statischen * Breite. Das ist Teil der Verwirrung ... (1) Warum berechnen Sie 80% der Bildbreite? Das ändert sich nicht. Mehr, (2) Um diese * statische * Breite zu behalten, ändern Sie die Konstanten - möglicherweise wird es mit den Multiplikatoren funktionieren, aber ich denke nicht - von dem führenden * und * nach einem negativen Wert, um nach links und zurück zu ihrem Original zu verschieben Wert nach rechts verschieben. Ich dachte, das ist das, was du gesagt hast? Was vermisse ich? – dfd