web-dev-qa-db-fra.com

Masquer un UIView en utilisant des contraintes AutoLayout

De temps en temps, j'ai une sous-vue que je voudrais supprimer d'une mise en page. Non seulement elle devrait être cachée, mais elle ne devrait pas être considérée comme faisant partie du "flux" de la vue, pour ainsi dire. Un exemple:

enter image description here

Je recherche une stratégie pour masquer la vue orange par programmation. La mise en page des boîtes et leur contenu se font par autolayout. Deux choses à noter:

  • la boîte orange définit sa hauteur verticale en fonction du contenu, plus quelques décalages haut/bas pour les marges. Par conséquent, si vous définissez le texte des étiquettes sur nil, la vue sera réduite à ses marges internes, elle n'aura pas la hauteur 0.
  • De même, l'espacement vertical entre les trois cases signifie que même si la hauteur de la case orange est 0, l'écart entre le rouge et le jaune sera deux fois plus grand que nécessaire.

Une solution possible

Ma meilleure suggestion consiste à ajouter une contrainte à la zone orange, en définissant sa hauteur à 0. Pour que cela fonctionne, je dois utiliser des priorités non requises pour toutes les contraintes verticales à l'intérieur de la zone. Dans le même temps, le conteneur doit mettre à jour la constante pour la contrainte qui sépare les zones. Je n'aime pas trop cette approche car la classe orange définit ses contraintes internes en tenant compte du comportement de Superview. Je pourrais peut-être vivre avec si la vue de la boîte orange expose plutôt une méthode de «réduction» qui ajoute la contrainte de hauteur 0 elle-même.

Est-ce qu'il y a une meilleure approche?

28
Ben Packard

Pour ce faire, vous devez ajouter une contrainte supplémentaire entre les vues jaune et rouge d’une priorité inférieure et ajuster les priorités dans le code. 

enter image description here

La contrainte en tirets courts (orangeToRedCon est le point de vente) a une priorité de 999 (vous ne pouvez pas changer une priorité requise en une non-requise, c'est pourquoi elle n'est pas 1 000). La contrainte en tirets longs (yellowToRedCon) a une priorité de 500 et une constante de 20. En code, vous pouvez masquer la vue orange et échanger ces niveaux de priorité. défini pour la valeur constante de yellowToRedCon.

-(void)changePriorities {
    self.yellowToRedCon.priority = 999;
    self.orangeToRedCon.priority = 500;
    [UIView animateWithDuration:.5 animations:^{
        self.orangeView.alpha = 0;
        [self.view layoutIfNeeded];
    }];
}

Cette méthode ne nécessite aucune modification de la hauteur de la vue orange.

68
rdelmar

Dans iOS 9, vous pouvez utiliser UIStackView pour cela . Il existe également des polyfill pour les versions antérieures: TZStackView et OAStackView

13
fabb

Ce que vous pouvez faire est d’avoir la contrainte de hauteur de la vue orange comme sortie (pour pouvoir y accéder) . Puis animer le repli comme ceci:

[UIView animateWithDuration:0.3 animations:^{
    orangeHeightConstraint.constant = 0;
    [self.view layoutIfNeeded]
}];

La vue orange devra avoir une contrainte supérieure à la vue rouge et une contrainte inférieure à la vue jaune . Assurez-vous également de vérifier les sous-vues de clip dans IB ou [orangeView clipsToBounds] par programme. 

1
Jad Feitrouni

Je résoudrais cela en incluant tous les espaces "nécessaires" d'une sous-vue dans la sous-vue elle-même. Par ici, 1. Hauteur de la vue rouge = partie rouge visible + espace inférieur 2. Hauteur de la vue orange = partie orange visible + espace inférieur 3. Hauteur de vue jaune = jaune visible + espace inférieur

Lorsque vous définissez la hauteur de la vue orange sur 0 avec Autolayout, l’espace inférieur sera également automatiquement réduit à 0.

0
Vinod Vishwanath