Depuis que j'ai découvert que AutoLayout
je l'utilise partout, maintenant j'essaye de l'utiliser avec un tableHeaderView
.
J'ai fait subclass
de UIView
tout ajouté (étiquettes , etc ...) Je voulais avec leurs contraintes, alors j'ajouté ce CustomView
au UITableView
' tableHeaderView
.
Tout fonctionne très bien sauf que le UITableView
s'affiche toujours au - dessus du CustomView
, par dessus, je veux dire qu'il CustomView
est sous le UITableView
donc il ne peut pas être vu!
Il semble que peu importe ce que je fais, le height
de UITableView
' tableHeaderView
est toujours 0 (de même que la largeur, x et y).
Ma question: est-il possible du tout d'accomplir cela sans régler le cadre manuellement ?
EDIT:
Le CustomView
' subview
que j'utilise a ces contraintes:
_title = [[UILabel alloc]init];
_title.text = @"Title";
[self addSubview:_title];
[_title keep:[KeepTopInset rules:@[[KeepEqual must:5]]]]; // title has to stay at least 5 away from the supperview Top
[_title keep:[KeepRightInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepLeftInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepBottomInset rules:@[[KeepMin must:5]]]];
J'utilise une bibliothèque pratique 'KeepLayout' car l'écriture manuelle des contraintes prend une éternité et beaucoup trop de lignes pour une seule contrainte, mais les méthodes s'expliquent d'elles-mêmes.
Et le UITableView
a ces contraintes:
_tableView = [[UITableView alloc]init];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_tableView];
[_tableView keep:[KeepTopInset rules:@[[KeepEqual must:0]]]];// These 4 constraints make the UITableView stays 0 away from the superview top left right and bottom.
[_tableView keep:[KeepLeftInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepRightInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepBottomInset rules:@[[KeepEqual must:0]]]];
_detailsView = [[CustomView alloc]init];
_tableView.tableHeaderView = _detailsView;
Je ne sais pas si je dois définir des contraintes directement sur le CustomView
, je pense que la hauteur du CustomView est déterminée par les contraintes sur le UILabel
"titre" qu'il contient.
EDIT 2: Après une autre enquête, il semble que la hauteur et la largeur du CustomView sont correctement calculées, mais le haut du CustomView est toujours au même niveau que le haut de l'UITableView et ils se déplacent ensemble lorsque je fais défiler.
la source
Réponses:
J'ai posé et répondu à une question similaire ici . En résumé, j'ajoute l'en-tête une fois et l'utilise pour trouver la hauteur requise. Cette hauteur peut ensuite être appliquée à l'en-tête, et l'en-tête est défini une deuxième fois pour refléter le changement.
Si vous avez des étiquettes multilignes, cela dépend également de la vue personnalisée définissant la valeur favoriteMaxLayoutWidth de chaque étiquette:
ou peut-être plus généralement:
Mise à jour janvier 2015
Malheureusement, cela semble encore nécessaire. Voici une version rapide du processus de mise en page:
J'ai trouvé utile de déplacer ceci dans une extension sur UITableView:
Usage:
la source
preferredMaxLayoutWidth
consiste à ajouter une contrainte de largeur (égale à la largeur de la vue du tableau) sur la vue d'en-tête avant l'utilisationsystemLayoutSizeFittingSize:
.self.tableView.tableHeaderView
let height = header.systemLayoutSizeFittingSize(CGSizeMake(CGRectGetWidth(self.bounds), 0), withHorizontalFittingPriority: UILayoutPriorityRequired, verticalFittingPriority: UILayoutPriorityFittingSizeLevel).height
header.setNeedsLayout() header.layoutIfNeeded() header.frame.size = header.systemLayoutSizeFitting(UILayoutFittingCompressedSize) self.tableHeaderView = header
fonctionnerait à iOS 10.2J'ai été incapable d'ajouter une vue d'en-tête en utilisant des contraintes (dans le code). Si je donne à ma vue une contrainte de largeur et / ou de hauteur, j'obtiens un plantage avec le message disant:
Lorsque j'ajoute une vue dans le storyboard à ma vue de table, cela ne montre aucune contrainte, et cela fonctionne bien comme vue d'en-tête, donc je pense que le placement de la vue d'en-tête n'est pas effectué à l'aide de contraintes. Cela ne semble pas se comporter comme une vue normale à cet égard.
La largeur correspond automatiquement à la largeur de la vue du tableau, la seule chose que vous devez définir est la hauteur - les valeurs d'origine sont ignorées, donc peu importe ce que vous y mettez. Par exemple, cela a bien fonctionné (comme le fait 0,0,0,80 pour le rect):
la source
translatesAutoresizingMaskIntoConstraints = NO
. L'activation de la traduction empêche l'erreur - je supposeUITableView
qu'à partir de la version 7.1, il ne tente pas de mettre en page automatiquement sa vue d'en-tête et veut quelque chose avec le cadre prédéfini.J'ai vu beaucoup de méthodes ici faire tellement de choses inutiles, mais vous n'avez pas besoin de beaucoup pour utiliser la mise en page automatique dans la vue d'en-tête. Il vous suffit de créer votre fichier xib, de mettre vos contraintes et de l'instancier comme ceci:
la source
Une autre solution consiste à distribuer la création de la vue d'en-tête au prochain appel de thread principal:
Remarque: il corrige le bogue lorsque la vue chargée a une hauteur fixe. Je n'ai pas essayé lorsque la hauteur de l'en-tête ne dépend que de son contenu.
ÉDITER :
Vous pouvez trouver une solution plus propre à ce problème en implémentant cette fonction et en l'appelant dans
viewDidLayoutSubviews
la source
tableHeaderView
est une sorte de buggy avec mise en page automatique. Il existe des solutions de contournement, comme celle-ci. Mais puisque je l' ai écrit, je l' ai trouvé une solution meilleure et plus propre ici stackoverflow.com/a/21099430/127493 en appelant son- (void)sizeHeaderToFit
enviewDidLayoutSubviews
Code:
la source
Extension de cette solution http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/ pour l'affichage du pied de page:
la source
self.tableFooterView.transform
partie? Pourquoi est-ce nécessaire?Vous pouvez obtenir la mise en page automatique pour vous fournir une taille à l'aide de la méthode systemLayoutSizeFittingSize .
Vous pouvez ensuite l'utiliser pour créer le cadre de votre application. Cette technique fonctionne chaque fois que vous avez besoin de connaître la taille d'une vue qui utilise la disposition automatique en interne.
Le code dans Swift ressemble à
Ou en Objective-C
Il convient également de noter que dans ce cas particulier, le remplacement de requireConstraintBasedLayout dans votre sous-classe entraîne une passe de mise en page, cependant les résultats de cette passe de mise en page sont ignorés et le cadre système défini sur la largeur de tableView et 0 hauteur.
la source
Ce qui suit a fonctionné pour moi.
UIView
comme vue d'en-tête.UIView
Le principal avantage que je vois est de limiter les calculs de cadres. Apple devrait vraiment mettre à jour
UITableView
l'API de pour rendre cela plus facile.Exemple utilisant SnapKit:
la source
Des choses étranges se produisent. systemLayoutSizeFittingSize fonctionne très bien pour iOS9, mais pas pour iOS 8 dans mon cas. Donc, ce problème se résout assez facilement. Obtenez simplement le lien vers la vue de dessous dans l'en-tête et dans viewDidLayoutSubviews après les limites de la vue d'en-tête de mise à jour super appel en insérant la hauteur comme CGRectGetMaxY (yourview.frame) + padding
UPD: La solution la plus simple qui soit : Ainsi, dans la vue d'en-tête, placez la sous-vue et épinglez-la à gauche , à droite , en haut . Dans cette sous-vue, placez vos sous-vues avec des contraintes de hauteur automatique. Après cela, donnez tout le travail à la mise en page automatique (aucun calcul requis)
En conséquence, la sous-vue s'agrandit / rétrécit comme elle le devrait, à la fin, elle appelle viewDidLayoutSubviews. Au moment où nous connaissons la taille réelle de la vue, définissez la hauteur de headerView et mettez-la à jour en la réaffectant. Fonctionne comme un charme!
Fonctionne également pour la vue pied de page.
la source
Mis à jour pour Swift 4.2
la source
vous pouvez ajouter une contrainte d'emplacement haut + horizontal entre l'en-tête et la vue du tableau, pour le placer correctement (si l'en-tête lui-même contient toutes les contraintes de mise en page internes nécessaires pour avoir un cadre correct)
dans la méthode tableViewController viewDidLoad
la source
Ma vue d'en-tête de table est une sous-classe UIView - j'ai créé une seule UIView contentView dans l'initialiseur, avec ses limites identiques à celles du cadre de la vue d'en-tête de table et j'ai ajouté tous mes objets en tant que sous-vue.
Ajoutez ensuite les contraintes pour vos objets dans la
layoutSubviews
méthode de la vue d'en-tête de table plutôt que dans l'initialiseur. Cela a résolu le crash.la source
Mon AutoLayout fonctionne très bien:
la source
Dans la plupart des cas, la meilleure solution est simplement de ne pas lutter contre le framework et d'adopter les masques autoresizing:
En utilisant des masques de redimensionnement automatique, vous indiquez au cadre comment votre vue doit changer sa taille lorsque la vue supervisée change de taille. Mais ce changement est basé sur le cadre initial que vous avez défini.
la source
Je sais que c'est un ancien article, mais après avoir parcouru tous les messages SO à ce sujet et passé un après-midi entier à jouer avec cela, j'ai finalement trouvé une solution propre et pourtant très simple.
Tout d'abord, ma hiérarchie de vues ressemble à ceci:
tableHeaderView
Maintenant, à l'intérieur de la vue (n ° 3), j'ai mis en place toutes les contraintes comme je le ferais normalement en incluant l'espace inférieur au conteneur. Cela permettra au conteneur (c'est-à-dire 3.View, c'est-à-dire headerView) de se dimensionner en fonction de ses sous-vues et de leurs contraintes.
Après cela, j'ai défini les contraintes entre
3. View
et2. View
pour ceux-ci:Remarquez que j'omets intentionnellement l'espace du bas intentionnellement.
Une fois que tout cela est fait dans le storyboard, il ne reste plus qu'à coller ces trois lignes de codes:
la source
Conseils: Si vous utilisez la méthode setAndLayoutTableHeaderView, vous devez mettre à jour le cadre des sous-vues, donc dans cette situation, le favoriteMaxLayoutWidth d'UILabel doit appeler avant que systemLayoutSizeFittingSize soit appelé, ne pas appeler dans layoutSubview.
code show
la source
Partagez mon approche.
UITableView+XXXAdditions.m
Usage.
la source
Dans mon cas, la méthode avec systemLayoutSizeFittingSize pour une raison quelconque n'a pas fonctionné. Ce qui a fonctionné pour moi, c'est une modification de la solution publiée par HotJard (sa solution originale ne fonctionnait pas non plus dans mon cas sur iOS 8). Ce que je devais faire, c'est dans la vue d'en-tête, placer une sous-vue et l'épingler à gauche, à droite, en haut (ne pas épingler en bas). Mettez tout en utilisant la mise en page automatique dans cette sous-vue et dans le code, procédez comme suit:
la source
Un vieux poste. Mais un bon post. Voici mes 2 cents.
Tout d'abord, assurez-vous que votre vue d'en-tête a ses contraintes arrangées de manière à pouvoir prendre en charge sa propre taille de contenu intrinsèque. Ensuite, procédez comme suit.
la source
J'ai pu y parvenir par l'approche suivante (cela fonctionne pour le pied de page de la même manière).
Tout d'abord, vous aurez besoin d'une petite
UITableView
extension:Swift 3
Dans votre implémentation de classe de contrôleur de vue:
Remarques sur l'
UIView
implémentation de sous -vue d'un en-tête :Vous devez être sûr à 100% que votre vue d'en-tête a la configuration de mise en page automatique correcte. Je recommanderais de commencer avec une vue d'en-tête simple avec une seule contrainte de hauteur et d'essayer la configuration ci-dessus.
Remplacer
requiresConstraintBasedLayout
et retournertrue
:.
la source
Pour les utilisateurs Xamarin:
En supposant que vous ayez nommé la vue d'en-tête de votre tableview comme TableviewHeader
la source
Voici comment faire dans votre
UIViewController
la source
Tout basé sur des contraintes
UIView
peut être un bientableHeaderView
.Il faut définir un
tableFooterView
avant, puis imposer une contrainte de fin supplémentaire surtableFooterView
ettableHeaderView
.}
On peut trouver tous les détails et extraits de code ici
la source
J'ai trouvé une solution de contournement. encapsulez votre vue d'en-tête xib écrite de mise en page automatique dans un wrapper uiview vide et affectez la vue d'en-tête à la propriété tableViewHeader de tableView.
la source
Voici ce qui fonctionne pour UITableViewController dans iOS 12,
Drap un UIView dans le TableView au-dessus de toutes les cellules prototypes pour l'en-tête et au-dessous de toutes les cellules prototypes pour le pied de page. Configurez votre en-tête et votre pied de page selon vos besoins. Définissez toutes les contraintes requises.
Maintenant, utilisez les méthodes d'extension suivantes
et appelez-le dans ViewDidLayoutSubviews de la sous-classe de UITableViewController
la source
J'ai rencontré le problème d'obtenir une largeur de 375pt, le seul moyen qui a fonctionné pour moi est de relayer la tableView pour obtenir la largeur correcte. J'ai également préféré la mise en page automatique à la définition de la taille du cadre.
Voici la version qui fonctionne pour moi:
Xamarin.iOS
Version Swift (modifiée à partir de la réponse @Ben Packard)
la source
J'ai créé une sous-classe de
UITableView
et utiliséUIStackView
à la fois pour l'en-tête et le pied de page, cela permet également de définir plus d'une vue.https://github.com/omaralbeik/StackableTableView
la source
Ma solution est de créer une nouvelle classe comme celle-ci.
Pour l'utiliser, ajoutez simplement toutes vos sous-vues sur une instance de
BaseTableHeaderView
et attachez-la à votre vue de tableau.Il se redimensionnera automatiquement en fonction de ses contraintes.
la source
La réponse acceptée n'est utile que pour les tableaux avec une seule section. Pour les sections multiples,
UITableView
assurez-vous simplement que votre en-tête hérite deUITableViewHeaderFooterView
et tout ira bien.Au lieu de cela, intégrez simplement votre en-tête actuel dans le
contentView
fichierUITableViewHeaderFooterView
. Exactement comme desUITableViewCell
œuvres.la source
tableHeaderView
ne concerne pas l'en-tête de la section.