2016-07-16 2 views
-2

Ich möchte zwei Ansichten an der gleichen Position mit "Auto Layout Visual Format" in Swift, wie mache ich das auf elegante Weise?Wie lege ich zwei Ansichten an der gleichen Position mit "Auto Layout Visual Format"?

Ich war erfolgreich mit NSLayoutConstraint, aber ich hoffe, ich kann immer noch eine elegante Art und Weise mit visuellen Format finden.

Mein Code NSLayoutConstraint mit:

NSLayoutConstraint(item: greenView, attribute: .Left, relatedBy: .Equal, toItem: redView, attribute: .Left, multiplier: 1.0, constant: 0).active = true 
     NSLayoutConstraint(item: greenView, attribute: .Top, relatedBy: .Equal, toItem: redView, attribute: .Top, multiplier: 1.0, constant: 0).active = true 
     NSLayoutConstraint(item: greenView, attribute: .Right, relatedBy: .Equal, toItem: redView, attribute: .Right, multiplier: 1.0, constant: 0).active = true 
     NSLayoutConstraint(item: greenView, attribute: .Bottom, relatedBy: .Equal, toItem: redView, attribute: .Bottom, multiplier: 1.0, constant: 0).active = true 
+1

Durch Lesen der Dokumente? Dies ist keine "Do my work for me" -Seite. Machen Sie einen Versuch, es selbst zu tun, und wenn Sie es nicht funktionieren können, posten Sie Ihren Code hier und wir werden Ihnen helfen, es zu debuggen. –

+1

@DuncanC Ich denke nicht, dass es eine unangemessene Frage ist. Ich habe daran gearbeitet. Ich arbeite gerade jetzt daran. Ich habe keine ähnliche Frage auf SO gesehen, also habe ich sie gepostet. Und ich dachte, es ist eine einfache, klare Frage, die ich brauche, um meinen falschen Code nicht zu posten. Ich werde mehr suchen und meins später veröffentlichen. – allenlinli

Antwort

2

Die Visuelle Format Sprache können nicht für jeden möglichen Fall verwendet werden. Ich glaube, dass die Aneinanderreihung der beiden Ansichten ein solcher Fall ist.

Ich würde Sie Anker verwenden Layout vorschlagen stattdessen wie folgt aus:

override func viewDidLoad() { 
    super.viewDidLoad() 

    let redView = UIView() 
    redView.backgroundColor = .redColor() 
    redView.translatesAutoresizingMaskIntoConstraints = false 

    view.addSubview(redView) 

    let greenView = UIView() 
    greenView.backgroundColor = .greenColor() 
    greenView.translatesAutoresizingMaskIntoConstraints = false 

    view.addSubview(greenView) 

    let redHoriz = NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[redView]-20-|", options: [], metrics: nil, views: ["redView": redView]) 
    NSLayoutConstraint.activateConstraints(redHoriz) 

    let redVert = NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[redView]-50-|", options: [], metrics: nil, views: ["redView": redView]) 
    NSLayoutConstraint.activateConstraints(redVert) 

    // Set greenView to occupy same space as the redView 
    greenView.leftAnchor.constraintEqualToAnchor(redView.leftAnchor).active = true 
    greenView.rightAnchor.constraintEqualToAnchor(redView.rightAnchor).active = true 
    greenView.topAnchor.constraintEqualToAnchor(redView.topAnchor).active = true 
    greenView.bottomAnchor.constraintEqualToAnchor(redView.bottomAnchor).active = true 
} 

Die Visuelle Format Sprache können Sie Teile der Ansichten auszurichten. Zum Beispiel können Sie die Oberseiten der Unterseiten von zwei Ansichten ausrichten, indem Sie [.AlignAllTop, .AlignAllBottom] als das options Argument von constraintsWithFormat übergeben. Sie können jedoch nur Werte ausrichten, die senkrecht zur Richtung des visuellen Formats sind. Wenn Sie also ein horizontales Layout angeben, können Sie die Oberseiten und Unterseiten der Ansichten ausrichten. Wenn Sie ein vertikales Layout angeben, können Sie die linken und Rechte ausrichten.

Sie können zwei Ansichten ausrichten, indem Sie zwei zusätzliche Ansichten einfügen. In dem Beispiel unten, nimmt die blaue Ansicht, um die oben und untere Ausrichtung der roten Ansicht, und die gelbe Ansicht nimmt die und rechts Ausrichtung der roten Ansicht von links. Dann wird die grüne Ansicht ausgerichtet auf die oben und Boden der blauen Ansicht und die links und rechts der gelben Ansicht, so dass es auf die rote Ansicht ausgerichtet ist.

Schließlich, das Verstecken der blauen und gelben Ansichten lässt Sie mit dem Setup, das Sie wünschen.

VFL example

let redView = UIView() 
    redView.backgroundColor = .redColor() 
    redView.translatesAutoresizingMaskIntoConstraints = false 

    view.addSubview(redView) 

    let greenView = UIView() 
    greenView.backgroundColor = .greenColor() 
    greenView.translatesAutoresizingMaskIntoConstraints = false 

    view.addSubview(greenView) 

    let blueView = UIView() 
    blueView.translatesAutoresizingMaskIntoConstraints = false 
    blueView.backgroundColor = .blueColor() 
    blueView.hidden = true 

    view.addSubview(blueView) 

    let yellowView = UIView() 
    yellowView.translatesAutoresizingMaskIntoConstraints = false 
    yellowView.backgroundColor = .yellowColor() 
    yellowView.hidden = true 

    view.addSubview(yellowView) 

    let redHoriz = NSLayoutConstraint.constraintsWithVisualFormat("H:|-80-[redView]-80-|", options: [], metrics: nil, views: ["redView": redView]) 
    NSLayoutConstraint.activateConstraints(redHoriz) 

    let redVert = NSLayoutConstraint.constraintsWithVisualFormat("V:|-80-[redView]-80-|", options: [], metrics: nil, views: ["redView": redView]) 
    NSLayoutConstraint.activateConstraints(redVert) 

    let blueHorizVert = NSLayoutConstraint.constraintsWithVisualFormat("H:[redView][blueView]|", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: ["redView": redView, "blueView": blueView]) 
    NSLayoutConstraint.activateConstraints(blueHorizVert) 

    let yellowHorizVert = NSLayoutConstraint.constraintsWithVisualFormat("V:[redView][yellowView]|", options: [.AlignAllLeft, .AlignAllRight], metrics: nil, views: ["redView": redView, "yellowView": yellowView]) 
    NSLayoutConstraint.activateConstraints(yellowHorizVert) 

    let greenTopBottom = NSLayoutConstraint.constraintsWithVisualFormat("H:[greenView][blueView]|", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: ["greenView": greenView, "blueView": blueView]) 
    NSLayoutConstraint.activateConstraints(greenTopBottom) 

    let greenLeftRight = NSLayoutConstraint.constraintsWithVisualFormat("V:[greenView][yellowView]|", options: [.AlignAllLeft, .AlignAllRight], metrics: nil, views: ["greenView": greenView, "yellowView": yellowView]) 
    NSLayoutConstraint.activateConstraints(greenLeftRight) 

So Sie können tun es mit VFL, aber es ist nicht elegant. Ich würde vorschlagen, dass Sie bei der Verwendung von Ankern bleiben.

+0

Vielen Dank für die Antwort. Ich wusste nicht, wie man alignAnchor benutzt. Ich war erfolgreich mit NSLayoutConstraint. Aber ich hoffe, ich kann immer noch einen eleganten Weg finden, indem ich das visuelle Layout des Auto-Layouts benutze. – allenlinli

+0

Nur nur NSConstraint manuell. Ich habe meinen Code in der Frage hinzugefügt. Hilf mir, diese Frage offen zu halten: p – allenlinli

+0

Ich habe einen Weg gefunden, es mit VFL zu machen, aber es ist nicht elegant *. – vacawama

5

Ich würde Echo what vacawama said in his excellent answer über die Verwendung von Layout-Anker. Es ist wahrscheinlich so klar und elegant wie die native API, aber bitte beachten Sie, dass es iOS 9 und höher erfordert.

Zum Zwecke der Code Organisation, würde Ich mag statt vorzuschlagen für knappere Code suchen, organisieren Sie den Code in Methoden und/oder Erweiterungen, zum Beispiel:

extension UIView { 

    func constraintsAligningAllEdges(toView view2: UIView) -> [NSLayoutConstraint] { 

     return [ topAnchor.constraintEqualToAnchor(view2.topAnchor), 
       bottomAnchor.constraintEqualToAnchor(view2.bottomAnchor), 
       leadingAnchor.constraintEqualToAnchor(view2.leadingAnchor), 
       trailingAnchor.constraintEqualToAnchor(view2.trailingAnchor) ] 
    } 
} 

es verwenden würde wie folgt aussehen :

NSLayoutConstraint.activateConstraints(greenView.constraintsAligningAllEdges(toView: redView)) 

... oder vielleicht eine Klassenfunktionserweiterung für NSLayoutConstraint machen.

Zum Thema Visual Format Language, vacawama brachte auch eine sehr interessante Verwendung der Layout-Optionen. Hier ist eine andere Art und Weise, um das gleiche Ziel zu erreichen:

let views = ["greenView" : greenView, "redView" : redView] 

NSLayoutConstraint.activateConstraints(
    NSLayoutConstraint.constraintsWithVisualFormat("H:[greenView]-([email protected])-[redView]", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: views) + 
    NSLayoutConstraint.constraintsWithVisualFormat("V:[greenView]-([email protected])-[redView]", options: [.AlignAllLeading, .AlignAllTrailing], metrics: nil, views: views) 
) 

Was ich hier getan ist, anstatt zusätzliche Ansichten der Einführung, ich zwei Fremd Einschränkungen eingeführt haben, eine zwischen grünen Boden & rot oben, ein anderer zwischen grün Trailing & oben führenden. Beide haben jedoch die niedrigste Priorität von 1, so dass normalerweise andere Einschränkungen die Größe/Position beider Ansichten bestimmen. Sie sollten keinen Schaden anrichten.

Ist das etwas eleganter? Ich weiß nicht, aber persönlich denke ich, dass Layout-Anker für mich mehr Sinn machen, und Frameworks von Drittanbietern wie SnapKit sind auch gute Optionen.

+0

Ausgezeichnet. Gute Antwort. – vacawama

+1

Das gab mir eine andere Idee. Sie können 'constrainers.filter {$ 0.priority! = 1}' verwenden, um diese zusätzlichen Einschränkungen vollständig zu entfernen, bevor Sie sie aktivieren. – vacawama

+0

Das ist erstaunlich Jungs! würde diese sein '' ' NSLayoutConstraint.activateConstraints ( NSLayoutConstraint.constraintsWithVisualFormat ("H: [Greenview] - (0 @ 1) - [RedView]", Optionen: [.AlignAllTop, .AlignAllBottom], Metriken: nil, Ansichten: Ansichten) .filter {$ 0.priority! = 1} + NSLayoutConstraint.constraintsWithVisualFormat ("V: [greenView] - (0 @ 1) - [redView]", Optionen: [.AlignAllLeading, .AlignAllTrailing], metrics: nil, views: views) .filter {$ 0.priority! = 1} ) '' ' – allenlinli

Verwandte Themen