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
Réponses
Trop de publicités?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()
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];
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)]];
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
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()
}
- Réponses précédentes
- Plus de réponses