86 votes

Width and Height Equal to its superView using autolayout programmatically ?

J'ai cherché beaucoup de snippets sur le net et je n'ai toujours pas trouvé la réponse à mon problème. Ma question est que j'ai un scrollView(SV) et je veux ajouter un bouton à l'intérieur du scrollView(SV) programmatiquement avec la même largeur et hauteur de son superview qui est scrollView(SV) de sorte que lorsque l'utilisateur tourne le périphérique le bouton aura le même cadre du scrollView(SV). comment faire le NSLayout/NSLayoutConstraint ? merci

128voto

MadNik Points 1131

Si quelqu'un cherche un Une solution rapide - Je créerais un fichier Swift extension pour UIView qui vous aidera chaque fois que vous voudrez lier le cadre d'une vue secondaire aux limites de sa vue principale :

Swift 2 :

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[subview]-0-|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }

}

Swift 3 :

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
    }
}

Swift 4.2 :

extension UIView {

    /// Adds constraints to this `UIView` instances `superview` object to make sure this always has the same size as the superview.
    /// Please note that this has no effect if its `superview` is `nil` – add this `UIView` instance as a subview before calling this.
    func bindFrameToSuperviewBounds() {
        guard let superview = self.superview else {
            print("Error! `superview` was nil – call `addSubview(view: UIView)` before calling `bindFrameToSuperviewBounds()` to fix this.")
            return
        }

        self.translatesAutoresizingMaskIntoConstraints = false
        self.topAnchor.constraint(equalTo: superview.topAnchor, constant: 0).isActive = true
        self.bottomAnchor.constraint(equalTo: superview.bottomAnchor, constant: 0).isActive = true
        self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: 0).isActive = true
        self.trailingAnchor.constraint(equalTo: superview.trailingAnchor, constant: 0).isActive = true

    }
}

Il suffit alors de l'appeler ainsi :

// after adding as a subview, e.g. `view.addSubview(subview)`
subview.bindFrameToSuperviewBounds()

70voto

Bordz Points 683

Je ne suis pas sûr que ce soit la façon la plus efficace de procéder, mais cela fonctionne

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.translatesAutoresizingMaskIntoConstraints = NO;
// initialize

[coverForScrolView addSubview:button];

NSLayoutConstraint *width =[NSLayoutConstraint
                                    constraintWithItem:button
                                    attribute:NSLayoutAttributeWidth
                                    relatedBy:0
                                    toItem:coverForScrolView
                                    attribute:NSLayoutAttributeWidth
                                    multiplier:1.0
                                    constant:0];
NSLayoutConstraint *height =[NSLayoutConstraint
                                     constraintWithItem:button
                                     attribute:NSLayoutAttributeHeight
                                     relatedBy:0
                                     toItem:coverForScrolView
                                     attribute:NSLayoutAttributeHeight
                                     multiplier:1.0
                                     constant:0];
NSLayoutConstraint *top = [NSLayoutConstraint
                                   constraintWithItem:button
                                   attribute:NSLayoutAttributeTop
                                   relatedBy:NSLayoutRelationEqual
                                   toItem:coverForScrolView
                                   attribute:NSLayoutAttributeTop
                                   multiplier:1.0f
                                   constant:0.f];
NSLayoutConstraint *leading = [NSLayoutConstraint
                                       constraintWithItem:button
                                       attribute:NSLayoutAttributeLeading
                                       relatedBy:NSLayoutRelationEqual
                                       toItem:coverForScrolView
                                       attribute:NSLayoutAttributeLeading
                                       multiplier:1.0f
                                       constant:0.f];
[coverForScrolView addConstraint:width];
[coverForScrolView addConstraint:height];
[coverForScrolView addConstraint:top];
[coverForScrolView addConstraint:leading];

49voto

I-droid Points 868

Ce lien peut vous aider, suivez les instructions : http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2

EDIT :

utilisez l'extrait de code suivant, où subview est votre sous-vue.

[subview setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(subview)]];
[self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"V:|-0-[subview]-0-|"
                           options:NSLayoutFormatDirectionLeadingToTrailing
                           metrics:nil
                           views:NSDictionaryOfVariableBindings(subview)]];

20voto

beryllium Points 18138

addConstraint y removeConstraint pour UIView vont être dépréciées, il est donc utile d'utiliser les "commodités de création de contraintes" :

view.topAnchor.constraint(equalTo: superView.topAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: superView.bottomAnchor, constant: 0).isActive = true
view.leadingAnchor.constraint(equalTo: superView.leadingAnchor, constant: 0).isActive = true
view.trailingAnchor.constraint(equalTo: superView.trailingAnchor, constant: 0).isActive = true

8voto

Dschee Points 8441

Approche n° 1 : via l'extension UIView

Voici une plus fonctionnel approche en Swift 3+ avec un condition préalable au lieu d'un print (qui peut facilement périr dans la console). Celui-ci signaler les erreurs du programmeur comme des constructions ratées.

Ajouter cette extension à votre projet :

extension UIView {
    /// Adds constraints to the superview so that this view has same size and position.
    /// Note: This fails the build if the `superview` is `nil` – add it as a subview before calling this.
    func bindEdgesToSuperview() {
        guard let superview = superview else {
            preconditionFailure("`superview` was nil – call `addSubview(view: UIView)` before calling `bindEdgesToSuperview()` to fix this.")
        }
        translatesAutoresizingMaskIntoConstraints = false
        ["H:|-0-[subview]-0-|", "V:|-0-[subview]-0-|"].forEach { visualFormat in
            superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: visualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        }
    }
}

Maintenant l'appeler simplement comme ceci :

// after adding as a subview, e.g. `view.addSubview(subview)`
subview.bindEdgesToSuperview()

Notez que la méthode ci-dessus est déjà intégré dans mon HandyUIKit qui ajoute également des aides à l'interface utilisateur dans votre projet.


Approche n°2 : Utilisation d'un cadre

Si vous travailler beaucoup avec des contraintes programmatiques dans votre projet, alors je vous recommande de vérifier SnapKit . Il facilite grandement le travail avec les contraintes. plus facile y moins sujettes aux erreurs .

Suivre le instructions d'installation dans la documentation pour inclure SnapKit dans votre projet. Ensuite l'importation au début de votre fichier Swift :

import SnapKit

Aujourd'hui, vous pouvez réaliser la même chose avec ceci :

subview.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X