J'ai conçu ma cellule personnalisée dans IB, je l'ai sous-classée et j'ai connecté mes prises à ma classe personnalisée. J'ai trois sous-vues dans le contenu des cellules qui sont: UIView (cdView) et deux étiquettes (titleLabel et emailLabel). En fonction des données disponibles pour chaque ligne, je souhaite parfois avoir UIView et deux étiquettes affichées dans ma cellule et parfois seulement deux étiquettes. Ce que j'essaie de faire, c'est de définir des contraintes de cette façon si je définis la propriété UIView sur caché ou que je la supprime de la vue d'ensemble, les deux étiquettes se déplaceront vers la gauche. J'ai essayé de définir la contrainte de tête UIView sur Superview (contenu de cellule) pour 10px et les contraintes de tête UILabels pour 10 px sur la vue suivante (UIView). Plus tard dans mon code
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
...
Record *record = [self.records objectAtIndex:indexPath.row];
if ([record.imageURL is equalToString:@""]) {
cell.cdView.hidden = YES;
}
Je cache mon cell.cdView et j'aimerais que les étiquettes se déplacent vers la gauche mais elles restent dans la même position dans Cell. J'ai essayé de supprimer cell.cdView de superview mais cela n'a pas fonctionné non plus. J'ai joint une image pour clarifier ce que je suis.
Je sais comment procéder par programme et je ne cherche pas cette solution. Ce que je veux, c'est définir des contraintes dans IB et je m'attends à ce que mes sous-vues se déplacent dynamiquement si d'autres vues sont supprimées ou masquées. Est-il possible de le faire dans IB avec la mise en page automatique?
.....
Réponses:
C'est possible, mais vous devrez faire un peu de travail supplémentaire. Il y a quelques éléments conceptuels à éviter en premier:
Dans votre cas, cela signifie probablement:
Ce que vous devez faire, c'est judicieusement surcharger vos étiquettes. Laissez vos contraintes existantes (espace de 10 pts à l'autre vue), mais ajoutez une autre contrainte: éloignez les bords gauches de vos étiquettes de 10 pts du bord gauche de leur vue d'ensemble avec une priorité non requise (la priorité élevée par défaut fonctionnera probablement bien).
Ensuite, lorsque vous souhaitez qu'ils se déplacent vers la gauche, supprimez complètement la vue de gauche. La contrainte obligatoire de 10 points sur la vue de gauche disparaîtra avec la vue à laquelle elle se rapporte, et il ne vous restera qu'une contrainte de haute priorité pour que les étiquettes soient à 10 pts de leur vue d'ensemble. Lors de la prochaine passe de mise en page, cela devrait les faire s'étendre vers la gauche jusqu'à ce qu'ils remplissent la largeur de la vue d'ensemble, mais pour votre espacement autour des bords.
Une mise en garde importante: si jamais vous voulez que votre vue de gauche revienne dans l'image, non seulement vous devez l'ajouter à nouveau dans la hiérarchie des vues, mais vous devez également rétablir toutes ses contraintes en même temps. Cela signifie que vous avez besoin d'un moyen de remettre votre contrainte d'espacement de 10 points entre la vue et ses étiquettes chaque fois que cette vue s'affiche à nouveau.
la source
|-(space)-[hidden(0)]-(space)-[visible]
c'est effectivement|-(2*space)-[visible]
. Deuxièmement, cette vue peut commencer à générer des violations de contraintes en fonction de son propre sous-arbre de vue et de ses propres contraintes - vous ne pouvez pas garantir que vous pouvez contraindre arbitrairement une vue à une largeur de 0 et la faire fonctionner.|-[otherViews]-[eitherThis][orThis]-|
, mais je me suis finalement heurté à ce problème.L'ajout ou la suppression de contraintes pendant l'exécution est une opération lourde qui peut affecter les performances. Cependant, il existe une alternative plus simple.
Pour la vue que vous souhaitez masquer, définissez une contrainte de largeur. Contraignez les autres vues avec un écart horizontal de tête à cette vue.
Pour masquer, mettez à jour la
.constant
contrainte de largeur à 0.f. Les autres vues se déplaceront automatiquement vers la gauche pour prendre position.Voir mon autre réponse ici pour plus de détails:
Comment changer les contraintes d'étiquette pendant l'exécution?
la source
Pour ceux qui prennent en charge iOS 8+ uniquement, une nouvelle propriété booléenne est active . Cela aidera à activer dynamiquement uniquement les contraintes nécessaires
La sortie de contrainte PS doit être forte , pas faible
Exemple:
Pour corriger une erreur dans le storyboard, vous devrez également décocher la
Installed
case pour l'une de ces contraintes.UIStackView (iOS 9+)
Une autre option consiste à encapsuler vos vues
UIStackView
. Une fois la vue masquéeUIStackView
, la mise à jour sera mise à jour automatiquementla source
UIStackView
repositionne automatiquement ses vues lorsque lahidden
propriété est modifiée sur l'une de ses sous-vues (iOS 9+).Aller à 11:48 dans cette vidéo WWDC pour une démo:
Mystères de la mise en page automatique, partie 1
la source
Mon projet utilise une
@IBDesignable
sous-classe personnalisée deUILabel
(pour assurer la cohérence de la couleur, de la police, des encarts, etc.) et j'ai mis en œuvre quelque chose comme ceci:Cela permet à la sous-classe d'étiquettes de participer à la mise en page automatique, mais ne prend pas d'espace lorsqu'elle est masquée.
la source
Pour les Googlers: en s'appuyant sur la réponse de Max, pour résoudre le problème de rembourrage que beaucoup ont remarqué, j'ai simplement augmenté la hauteur de l'étiquette et utilisé cette hauteur comme séparateur au lieu du rembourrage réel. Cette idée pourrait être développée pour tout scénario contenant des vues.
Voici un exemple simple:
Dans ce cas, je mappe la hauteur du libellé Auteur à un niveau approprié
IBOutlet
:et lorsque je règle la hauteur de la contrainte sur
0.0f
, nous conservons le "rembourrage", car la hauteur du bouton Lecture le permet.la source
NSLayoutConstraint
je crois que vous souhaitez mettre à jour laconstant
propriété de votreauthorLabelHeight
.connectez la contrainte entre uiview et les étiquettes en tant qu'IBOutlet et définissez le membre prioritaire sur une valeur inférieure lorsqu'il est masqué = YES
la source
J'ai fini par créer 2 xibs. Un avec la vue de gauche et un sans. J'ai enregistré les deux dans le contrôleur, puis j'ai décidé lequel utiliser pendant cellForRowAtIndexPath.
Ils utilisent la même classe UITableViewCell. L'inconvénient est qu'il y a une certaine duplication du contenu entre les xibs, mais ces cellules sont assez basiques. L'avantage est que je n'ai pas beaucoup de code pour gérer manuellement la suppression de la vue, la mise à jour des contraintes, etc.
En général, c'est probablement une meilleure solution car ce sont des dispositions techniquement différentes et devraient donc avoir des xibs différents.
la source
Dans ce cas, je mappe la hauteur du libellé Auteur à un IBOutlet approprié:
et quand je règle la hauteur de la contrainte à 0.0f, nous conservons le "padding", car la hauteur du bouton Play le permet.
la source
Utilisez deux UIStackView Horizontal et Vertical, quand une vue de sous-vue dans la pile est masquée, d'autres sous-vues de pile seront déplacées, utilisez Distribution -> Remplir proportionnellement pour la pile verticale avec deux UILabels et devez définir des contraintes de largeur et de hauteur pour la première UIView
la source
Essayez ceci, j'ai implémenté le code ci-dessous,
J'ai une vue sur ViewController dans laquelle trois autres vues ont été ajoutées. Lorsqu'une vue est masquée, deux autres vues se déplacent, suivez les étapes ci-dessous. ,
Fichier 1.ViewController.h
2.ViewController.m
Espérons que cette logique aidera quelqu'un.
la source
Dans mon cas, j'ai défini la constante de la contrainte de hauteur sur
0.0f
et également défini lahidden
propriété surYES
.Pour afficher à nouveau la vue (avec les sous-vues), j'ai fait le contraire: j'ai défini la constante de hauteur sur une valeur non nulle et défini la
hidden
propriété surNO
.la source
J'utiliserai stackview horizontal. Il peut supprimer le cadre lorsque la sous-vue est masquée.
Dans l'image ci-dessous, la vue rouge est le conteneur réel de votre contenu et dispose d'un espace de fin de 10 points à la vue d'ensemble orange (ShowHideView), puis connectez simplement ShowHideView à IBOutlet et affichez / masquez / supprimez-le par programme.
la source
C'est ma autre solution en utilisant la contrainte de priorité. L'idée est de définir la largeur à 0.
créer une vue conteneur (orange) et définir la largeur.
créer une vue de contenu (rouge) et définir l'espace de fin de 10 pt sur superview (orange). Remarquez les contraintes d'espace de fin, il y a 2 contraintes de fin avec une priorité différente. Faible (= 10) et élevée (<= 10). Ceci est important pour éviter toute ambiguïté.
Définissez la largeur de la vue orange sur 0 pour masquer la vue.
la source
Comme l'a suggéré no_scene, vous pouvez certainement le faire en modifiant la priorité de la contrainte lors de l'exécution. Cela a été beaucoup plus facile pour moi car j'avais plusieurs vues de blocage qui devaient être supprimées.
Voici un extrait utilisant ReactiveCocoa:
la source
Au cas où cela aiderait quelqu'un, j'ai construit une classe d'assistance pour utiliser les contraintes de format visuel . Je l'utilise dans mon application actuelle.
AutolayoutHelper
Il peut être un peu adapté à mes besoins, mais vous pouvez le trouver utile ou vous pouvez le modifier et créer votre propre assistant.
Je dois remercier Tim pour sa réponse ci - dessus , cette réponse sur UIScrollView et aussi ce tutoriel .
la source
Voici comment je réalignerais mes vues pour obtenir votre solution:
J'ai créé ma propre règle. Chaque fois que vous devez masquer / afficher une uiview dont les contraintes pourraient être affectées, ajoutez toutes les sous-vues affectées / dépendantes à l'intérieur d'une uiview et mettez à jour sa constante de contrainte de début / fin / haut / bas par programme.
la source
C'est une vieille question mais j'espère que ça va aider. Venant d'Android, dans cette plate-forme, vous avez une méthode pratique
isVisible
pour le cacher de la vue, mais pas non plus le cadre pris en compte lorsque la mise en page automatique dessine la vue.en utilisant extension et "extend" uiview, vous pouvez faire une fonction similaire dans ios (vous ne savez pas pourquoi il ne l'est pas déjà dans UIKit) ici une implémentation dans swift 3:
la source
la bonne façon de le faire est de désactiver les contraintes avec isActive = false. notez cependant que la désactivation d'une contrainte la supprime et la libère, vous devez donc disposer de sorties solides pour elles.
la source
La solution la plus simple consiste à utiliser UIStackView (horizontal). Ajouter à la vue de la pile: première vue et deuxième vue avec étiquettes. Définissez ensuite la propriété isHidden de la première vue sur false. Toutes les contraintes seront calculées et mises à jour automatiquement.
la source
Je pense que c'est la réponse la plus simple. Veuillez vérifier que cela fonctionne:
vérifiez ici https://www.youtube.com/watch?v=EBulMWMoFuw
la source