Wie kann ich in iOS programmgesteuert Einschränkungen für das Seitenverhältnis festlegen?

85

Ich habe das automatische Layout für meine Ansichtssteuerungen verwendet. Ich habe die V- und H-Positionen in Einschränkungen festgelegt, möchte aber wissen, wie ich meine Tastengröße erhöhen kann, wenn sie auf 5s, 6 und 6 Plus geändert wird. Auf diese Weise habe ich Einschränkungen für die Anmeldeschaltfläche hinzugefügt:

NSArray *btncon_V=[NSLayoutConstraint constraintsWithVisualFormat:@"V:[btnLogin(40)]" options:0 metrics:nil views:viewsDictionary];
[btnLogin addConstraints:btncon_V];

NSArray *btncon_POS_H=[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-100-[btnLogin]-100-|" options:0 metrics:nil views:viewsDictionary];
[self.view addConstraints:btncon_POS_H];


NSArray *btncon_POS_V=[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-70-[Title]-130-[lblFirst]-0-[lblSecond]-20-[textusername]-10-[txtpassword]-10-[btnLogin]" options:0 metrics:nil views:viewsDictionary];

[self.view addConstraints:btncon_POS_V];

Aber mein Problem ist, dass es zwar den linken und rechten Seitenabstand verwaltet, aber in iPhone 6 und 6 Plus gedehnt wird, da die Höhe festgelegt ist. Wie kann ich die Größe entsprechend der Bildschirmgröße erhöhen? Ich denke, dies könnte das Seitenverhältnis sein, aber wie kann ich die Seitenverhältnisbeschränkung im Code festlegen?

IRD
quelle
2
Überprüfen Sie diese Antwort: stackoverflow.com/a/12526630/3202193
Ashish Kakkad

Antworten:

84

So was. Versuch es einmal.

[self.yourview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.yourview addConstraint:[NSLayoutConstraint
                                  constraintWithItem:self.yourview
                                  attribute:NSLayoutAttributeHeight
                                  relatedBy:NSLayoutRelationEqual
                                  toItem:self.yourview
                                  attribute:NSLayoutAttributeWidth
                                  multiplier:(self.yourview.frame.size.height / self.yourview.frame.size.width)
                                  constant:0]];

oder anstelle von können (self.yourview.frame.size.height / self.yourview.frame.size.width)Sie einen beliebigen Gleitkommawert verwenden. Vielen Dank.

Swift 3.0 -

self.yourview!.translatesAutoresizingMaskIntoConstraints = false
self.yourview!.addConstraint(NSLayoutConstraint(item: self.yourview!,
                                          attribute: NSLayoutAttribute.height,
                                          relatedBy: NSLayoutRelation.equal,
                                          toItem: self.yourview!,
                                          attribute: NSLayoutAttribute.width,
                                          multiplier: self.yourview.frame.size.height / self.yourview.frame.size.width,
                                          constant: 0))
Mahesh Agrawal
quelle
Es gibt mir diesen Fehler Beenden der App aufgrund der nicht erfassten Ausnahme 'NSInternalInconsistencyException', Grund: 'Multiplikator ist nicht endlich! Das ist illegal. Multiplikator: nan '
IRD
2
In dem Szenario bedeutet dies, dass wenn die Höhe 100 und die Breite 200 beträgt und Sie mit meinem Code den Multiplikator 0,5 angegeben haben. Wenn sich Ihre Höhe durch Ändern einer anderen Einschränkung auf 150 erhöht, erhöht sich die Breite automatisch auf 300. Dazu müssen Sie jedoch um eine Einschränkung der Ansicht wie Breite oder Höhe zu erhöhen.
Mahesh Agrawal
1
Es dauert Höhe: Breite = 1: 2, das ist 0,5.
Mahesh Agrawal
3
Vergessen Sie nicht, diese Zeile hinzuzufügen, bevor Sie programmgesteuert Einschränkungen [self.yourview setTranslatesAutoresizingMaskIntoConstraints:NO];
festlegen
1
Bei Verwendung von Einschränkungen waren meine Rahmengrößen alle Null. Um das Seitenverhältnis zu erhalten, habe ich stattdessenself.yourview.intrinsicContentSize
Phlippie Bosman
88

Layout-Anker sind die bequemste Möglichkeit, Einschränkungen programmgesteuert festzulegen.

Angenommen, Sie möchten ein Seitenverhältnis von 5: 1 für Ihre Schaltfläche festlegen, dann sollten Sie Folgendes verwenden:

button.heightAnchor.constraint(equalTo: button.widthAnchor, multiplier: 1.0/5.0).isActive = true

Hier ist der vollständige Code:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = UIButton(type: .custom)
        button.setTitle("Login", for: .normal)
        button.backgroundColor = UIColor.darkGray

        self.view.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false

        let margins = view.layoutMarginsGuide

        button.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 20.0).isActive = true
        button.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: -20.0).isActive = true
        button.bottomAnchor.constraint(equalTo: margins.bottomAnchor, constant: -20.0).isActive = true
        button.heightAnchor.constraint(equalTo: button.widthAnchor, multiplier: 1.0/5.0).isActive = true
    }

}

Hier sind die Ergebnisse, die mit dem oben geschriebenen Code erzielt wurden. Sie können sehen, dass die Schaltfläche das Seitenverhältnis von 5: 1 für verschiedene Geräte beibehält:

Ergebnisansicht

Eugene Brusov
quelle
14

Swift 3:

yourView.addConstraint(NSLayoutConstraint(item: yourView,
                                          attribute: .height,
                                          relatedBy: .equal,
                                          toItem: yourView,
                                          attribute: .width,
                                          multiplier: 9.0 / 16.0,
                                          constant: 0))
RNHTTR
quelle
1
Für iOS 8 und höher sollten Sie die isActive-Eigenschaft von NSLayoutConstraint verwenden, anstatt addConstraint (:) aufzurufen. aspectRatioConstraint.isActive = true
dvdblk
Warum verwenden Sie nicht .widthals erstes Attribut? Das Ergebnis ist attr2 * multiplier , dass das Seitenverhältnis ist width / height. width = height * aspectRatioWenn wir also .heightdas erste Attribut und das erste setzen aspectRatio, multiplierist das Ergebnis vollständig umgekehrt.
Kimi Chiu
12

Sie können "Höhenbeschränkung" zur Entwurfszeit in Interface Builder festlegen. Aktivieren Sie einfach "Beim Erstellen entfernen" und es wird entfernt, wann die App ausgeführt wird.

Geben Sie hier die Bildbeschreibung ein Danach können Sie die Einschränkung "Seitenverhältnis" hinzufügen, z. B. in der viewDidLoad-Methode.

In Xamain.iOS für "16: 9" sieht es so aus:

    this.ImageOfTheDay.AddConstraint(NSLayoutConstraint.Create(
            this.ImageOfTheDay,
            NSLayoutAttribute.Height,
            NSLayoutRelation.Equal,
            this.ImageOfTheDay,
            NSLayoutAttribute.Width,
            9.0f / 16.0f,
            0));

Oder wie Mahesh Agrawal sagte:

    [self.ImageOfTheDay addConstraint:[NSLayoutConstraint
                              constraintWithItem:self.ImageOfTheDay
                              attribute:NSLayoutAttributeHeight
                              relatedBy:NSLayoutRelationEqual
                              toItem:self.ImageOfTheDay
                              attribute:NSLayoutAttributeWidth
                              multiplier:(9.0f / 16.0f)
                              constant:0]];
Zanael
quelle
12

Hilfserweiterung in UIView

extension UIView {

    func aspectRation(_ ratio: CGFloat) -> NSLayoutConstraint {

        return NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: self, attribute: .width, multiplier: ratio, constant: 0)
    }
}

Und Verwendung ist:

view.aspectRation(1.0/1.0).isActive = true

Michał Ziobro
quelle
und Verwendung: view.aspectRation (1.0 / 1.0)
Michał Ziobro
1
Dies ist in der Tat eine elegante Lösung, abgesehen von einigen Typen: 1. Der Parameter toItem wird auf .selfanstelle von self2 gesetzt. Und die Verwendung in Kommentaren sollte view.aspectRation(1.0/1.0).isActive = true ich in Xcode 10.2.1 Swift 5 testen.
Pankaj Kulkarni
3

Ich habe alle Antworten oben ausprobiert, aber nicht funktioniert, und dies ist meine Lösung mit Swift 3:

let newConstraint = NSLayoutConstraint(item: yourView, attribute: .width, relatedBy: .equal, toItem: yourView, attribute: .height, multiplier: 560.0/315.0, constant: 0)
yourView.addConstraint(newConstraint)
NSLayoutConstraint.activate([newConstraint])  
NSLayoutConstraint.deactivate(yourView.constraints)
yourView.layoutIfNeeded()
Tuandapen
quelle
Sie sollten immer (möglicherweise widersprüchliche) Einschränkungen deaktivieren, bevor Sie neue hinzufügen, um Autolayout-Fehler zu vermeiden
John
0

Für Ansichten gibt es Einschränkungen und auch Eigenschaften.

Das Seitenverhältnis ist eine Eigenschaft der Ansicht , sodass Sie es wie folgt im Inhaltsmodus festlegen können

imageView.contentMode = .scaleAspectFit

Dadurch wird erreicht, dass eine Ansicht beispielsweise die Verhältnisse nicht ändert, wenn

  • Die Höhe oder Breite ist größer als auf den Bildschirm passt
  • Die Höhe wurde fest codiert und kann daher nicht an unterschiedliche Bildschirmgrößen angepasst werden.
valeriana
quelle
Bei der Frage geht es nicht um die ImageView und ihren Inhaltsmodus, sondern um das automatische Layout und die Einschränkungen. Im Interface Builder können Sie eine Seitenverhältnisbeschränkung festlegen, die am Ende mit einem Multiplikator eine Einschränkung für Breite und Höhe erzeugt.
Gunhan
@ Gunhan Die Frage bezieht sich darauf, wie man es programmgesteuert einstellt. Es ist also gut zu wissen, dass es im Interface Builder eingestellt werden kann, aber für diese Frage irrelevant.
Valeriana
Ich denke, Sie haben falsch verstanden, was ich zuvor gesagt habe. In dieser Frage spricht niemand über ImageView. In der IT geht es um automatisches Layout und Einschränkungen, die programmgesteuert erstellt werden müssen. Was ich gesagt habe war, wenn Sie es im Interface Builder festlegen, wird eine Einschränkung von Breite zu Höhe erstellt. Ich habe dir nicht gesagt, dass du es über IB erstellen sollst. Um dasselbe programmgesteuert zu tun, müssen Sie es view.widthAnchor.constraint(equalTo: view.heightAnchor, multiplier: aspectRatio, constant: 0)so erstellen
Gunhan