Supprimer les contraintes de mise en page automatique pour un objet spécifique
j'ai un UIImageView
intégré dans un UIView
. Mon application utilise AutoLayout
, mais je veux supprimer constraints
pour le UIImageView
. Xcode
ne me permettra pas de supprimer le constraints
, y a-t-il un moyen de les désactiver pour un objet spécifique, les mettre à zéro, quelque chose?
6 réponses
je suis d'accord Xcode Auto-layout est horrible à utiliser si vous voulez quelque chose de particulier...
Ce que j'utilise pour supprimer les contraintes par programmation:
[detailsPhotoView removeConstraints:detailsPhotoView.constraints];
dans XCode 5 Il y a une option lors de l'édition des contraintes "Supprimer au moment de la compilation". Si cette option est activée, la contrainte sera automatiquement supprimée pendant l'exécution. L'option est là pour garder Interface Builder heureux si vous ne voulez pas de contraintes particulières.
il y a deux questions distinctes ici:
- comment utiliser Xcode pour configurer UIImageView sans contraintes
- comment permettre à L'UIImageView d'être panoramique et/ou redimensionné lorsque sa mise en page est gérée par des contraintes.
en ce qui concerne (1), jturton a raison. Tant que vous avez activé la mise en page automatique dans Xcode, Xcode garantira/exigera qu'il y ait suffisamment de contraintes pour déterminer de façon unique taille et emplacement de votre vue.
si vous n'avez pas spécifié manuellement assez de contraintes dans Xcode (via les" contraintes utilisateur " qui apparaissent en bleu dans l'inspecteur de mise en page), alors Xcode ajoutera de nouvelles contraintes qu'il devine (qui apparaissent en violet) jusqu'à ce qu'il y ait suffisamment de contraintes pour déterminer la mise en page.
si L'UIImageView n'avait pas de contraintes, sa disposition ne serait pas déterminée, donc vous ne pouvez pas configurer cela dans Xcode. Pour résoudre ce problème, ce qui vous devez utiliser Xcode pour configurer IBOutlets à toutes les contraintes que vous voulez supprimer, puis dans awakeFromNib: de votre UIViewController: vous supprimez manuellement les contraintes en appelant removecontraints:.
cependant, maintenant la disposition de votre UIImageView est sous-déterminée. Donc, à ce stade, vous voudrez ajouter manuellement de nouvelles contraintes qui vous permettront de déplacer et de redimensionner L'UIImageView, ce qui nous amène à la question (2).
en ce qui concerne (2), comment redimensionner et déplacer une vue dont la disposition est déterminée par des contraintes, la réponse est de configurer les reconnaisseurs de gestes comme d'habitude pour détecter les gestes pinch & pan, mais au lieu de ces reconnaisseurs de gestes appelant setFrame: pour modifier la vue, ils devraient modifier le paramètre constant
D'une NSLayoutConstraint qui détermine le cadre de L'UIImageView et ensuite appeler layoutifneed:, ce qui fera que le système de layout traduire immédiatement cette contrainte modifiée dans un nouveau cadre.
ainsi, par exemple, supposons que vous vouliez manipuler la vue UIImageView avec un ensemble de contraintes de mise en page qui étaient très similaires à celles de setaframe: calls. Dans ce cas, après avoir enlevé les contraintes configurées par Xcode, vous pouvez ajouter des contraintes à la vue qui spécifient sa largeur, sa hauteur, et son espace depuis le haut et à gauche de la superview. Puis le handler d'action pour votre reconnaissance de geste de pan, mettrait juste à jour le paramètre constant de la pacer reconnaissance de geste, et votre reconnaissance de geste de pincement pourrait simplement mettre à jour le paramètre constant des contraintes de hauteur et de largeur.
une autre façon de faire (2), qui est la même sous le capot mais qui pourrait être plus facile dans la pratique, est de régler translatesAutoresizingMaskIntoConstraints=YES
. Cela va faire deux choses. Cela fera que le système de mise en page automatique générera automatiquement des contraintes dans la superview de la vue basée sur l'autoresizingMask de la vue. La deuxième, c'est fondamental! – il entraînera le système de mise en page à traduire automatiquement les appels vers setaframe: en modifications de ces contraintes.
Vous ne peut pas ont pas de contraintes - vous devez avoir suffisamment de contraintes en place sans ambiguïté la taille et la position de chaque vue
vous can créez une vue redimensionnable qui est présentée en utilisant Autolayout.
par exemple, dans votre cas, vous pouvez créer des contraintes de positionnement - par exemple, épingler le centre de la vue d'image horizontalement et verticalement au centre de sa superview.
Vous pouvez également créer des contraintes de taille, horizontalement et verticalement. Voir ma réponse ici pour savoir comment faire cela. Créez des sorties pour ces deux contraintes (si vous utilisez interface builder). Vous pouvez avoir des contraintes de hauteur et de largeur d'un nombre spécifique, ou utiliser le multiplicateur pour faire un rapport d'aspect fixe.
en réponse à des gestes de pincement, vous pouvez ajuster les propriétés .constant
des deux contraintes de taille, et appeler setNeedsLayout
. Ce sera redimensionner votre image tout en gardant son centre épinglé.
si vous faites la suggestion de rapport d'aspect fixe ci-dessus, redimensionner une vue en utilisant des contraintes est en fait beaucoup plus simple que de définir le cadre.
vous pouvez appeler
[yourElement removeFromSuperview];
puis appelez
[yourSuperview addSubview:yourElement];
pour supprimer toutes les contraintes de yourElement
et l'ajouter à la vue.
il est important de mentionner que si vous faites ce qui précède sur quelque chose comme une catégorie uivi ou une extension, vous devez enregistrer une référence à la vue de superview avant de supprimer de superview:
var theSuperview = self.superview
self.removeFromSuperview()
theSuperview?.addSubview(self)
vous pourriez également avoir besoin de vous rendre fort au lieu de faible car Supprimer de superview pourrait vous faire perdre une référence à celui-ci.
si vous voulez simplement supprimer une vue d'une hiérarchie, appelez simplement [theView removeFromSuperview]
. Toute contrainte la concernant sera également supprimée.
cependant, parfois, vous pourriez aussi vouloir mettre une vue en arrière, ayant Temporairement enlevé.
pour ce faire, j'utilise la catégorie suivante sur UIView
. Il remonte la hiérarchie de la vue d'une vue v
à une certaine vue ultime de conteneur c
(habituellement votre contrôleur de vue (vue racine) et supprime les contraintes externes à v
. Ce sont des contraintes qui sont des frères et sœurs à v
, plutôt que des contraintes qui affectent seulement les enfants de v
. Vous pouvez cacher v
.
-(NSArray*) stealExternalConstraintsUpToView: (UIView*) superview
{
NSMutableArray *const constraints = [NSMutableArray new];
UIView *searchView = self;
while(searchView.superview && searchView!= superview)
{
searchView = searchView.superview;
NSArray *const affectingConstraints =
[searchView.constraints filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(NSLayoutConstraint *constraint, NSDictionary *bindings)
{
return constraint.firstItem == self || constraint.secondItem == self;
}]];
[searchView removeConstraints: affectingConstraints];
[constraints addObjectsFromArray: affectingConstraints];
}
return constraints;
}
La méthode passe en arrière supprimés contraintes dans un tableau que vous pouvez tenir quelque sorte que plus tard, vous pouvez ajouter les contraintes de retour.
l'Utiliser un peu comme ça...
NSArray *const removedConstraints = [viewToHide stealExternalConstraintsUpToView: self.view];
[viewToHide setHidden: YES];
et plus tard, remettre les contraintes en place.
à partir de iOS 8 Vous n'avez pas besoin de penser à l'endroit où les contraintes devraient être mises.
[NSLayoutConstraint activateConstraints: removedConstraints];
[viewToHide setHidden: NO];
avec les versions précédentes de iOS vous n'avez pas besoin de réfléchir à l'endroit où ajouter les contraintes de retour. Lancez ensuite dans le contrôleur self.view
. Si les contraintes sont dans a superview de toutes les vues qu'ils affectent, ils seront travail.
[self.view addConstraints: removedConstraints];
[viewToHide setHidden: NO];