J'ai une configuration uilabel dans une vue. Il n'a pas de contrainte de largeur, mais sa largeur est plutôt déterminée par une contrainte principale de la vignette et une contrainte de fin sur le bord de la vue.
L'étiquette est définie pour avoir 0 lignes et pour le retour à la ligne. Si j'ai bien compris, cela devrait entraîner la croissance du cadre de uilabel, et c'est même parfois le cas. (Avant la mise en page automatique, je calculais et mettais à jour le cadre de l'étiquette en code).
Le résultat est que cela fonctionne correctement dans certains cas et pas dans d'autres. Voir que la plupart des cellules fonctionnent correctement ici, mais la dernière cellule semble être trop grande. En fait, c'est la bonne taille. Le titre "Test de vérification du smog de Fair Oaks" se termine en réalité par "Seulement". Donc, mon calcul pour la taille de la cellule est exact, il devrait être de cette taille. Cependant, l’étiquette n’enveloppe pas le texte pour une raison quelconque. La largeur du cadre ne va pas à droite, ce n'est donc pas le problème.
Que se passe-t-il? C’est cohérent à 100%, toujours sur cette cellule et non sur celles au-dessus, ce qui me fait penser que cela est lié à la taille du texte, et UILabel ne remet pas en forme le texte une fois cette vue ajoutée à la cellule le rend réellement plus petit en largeur).
Des pensées?
La hauteur des cellules est calculée à partir d'une cellule d'échantillon que je crée et stocke dans une variable statique:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.items.count == 0) {
return 60;
}
static TCAnswerBuilderCell *cell = nil;
static dispatch_once_t pred;
dispatch_once(&pred,
^{
// get a sample cellonce
cell = [tableView dequeueReusableCellWithIdentifier:TC_ANSWER_BUILDER_CELL];
});
[cell configureCellWithThirdPartyObject:self.items[indexPath.row]];
return [cell heightForCellWithTableWidth:self.tableView.frame.size.width];
}
Je configure la cellule avec mon objet de données à la volée, puis appelle une méthode que j'ai sur elle qui calcule la hauteur de la cellule avec une largeur de tableau donnée (ne peut pas toujours compter sur le cadre de la cellule étant initialement correct).
Ceci à mon tour appelle une méthode de hauteur à mon avis, puisque c’est là que vit réellement le label:
- (CGFloat)heightForCellWithTableWidth:(CGFloat)tableWidth {
// subtract 38 from the constraint above
return [self.thirdPartyAnswerView heightForViewWithViewWidth:tableWidth - 38];
}
Cette méthode détermine la hauteur en déterminant la largeur correcte de l'étiquette, puis en effectuant un calcul:
- (CGFloat)heightForViewWithViewWidth:(CGFloat)viewWidth {
CGFloat widthForCalc = viewWidth - self.imageFrameLeadingSpaceConstraint.constant - self.thumbnailFrameWidthConstraint.constant - self.titleLabelLeadingSpaceConstraint.constant;
CGSize size = [self.titleLabel.text sizeWithFont:self.titleLabel.font constrainedToSize:CGSizeMake(widthForCalc, CGFLOAT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
CGFloat returnHeight = self.frame.size.height - self.titleLabel.frame.size.height + size.height;
CGFloat height = returnHeight < self.frame.size.height ? self.frame.size.height : returnHeight;
return height;
}
Cela fonctionne à 100% correctement.
Les cellules sont évidemment créées dans cellForRowAtIndexPath et immédiatement configurées:
if (self.items.count > 0) {
TCAnswerBuilderCell *cell = [tableView dequeueReusableCellWithIdentifier:TC_ANSWER_BUILDER_CELL forIndexPath:indexPath];
[cell configureCellWithThirdPartyObject:self.items[indexPath.row]];
return cell;
}
Dans la configuration de la cellule, ma vue est chargée depuis un nib (elle est réutilisée ailleurs, c'est pourquoi elle n'est pas directement dans la cellule). La cellule l'ajoute comme suit:
- (void) configureCellWithThirdPartyObject:(TCThirdPartyObject *)object {
self.detailDisclosureImageView.hidden = NO;
if (!self.thirdPartyAnswerView) {
self.thirdPartyAnswerView = [TCThirdPartyAPIHelper thirdPartyAnswerViewForThirdPartyAPIServiceType:object.thirdPartyAPIType];
self.thirdPartyAnswerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.thirdPartyAnswerView];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[_thirdPartyAnswerView]-38-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:NSDictionaryOfVariableBindings(_thirdPartyAnswerView)]];
}
[self.thirdPartyAnswerView configureViewForThirdPartyObject:object forViewStyle:TCThirdPartyAnswerViewStyleSearchCell];
}
Enfin, ma configuration de vue ressemble à ceci:
- (void) configureViewForThirdPartyObject:(TCTPOPlace *)object forViewStyle:(TCThirdPartyAnswerViewStyle) style {
self.titleLabel.text = object.name;
self.addressLabel.text = [NSString stringWithFormat:@"%@, %@, %@", object.address, object.city, object.state];
self.ratingsLabel.text = [NSString stringWithFormat:@"%d Ratings", object.reviewCount];
NSString *ratingImageName = [NSString stringWithFormat:@"Yelp_star_rating_%.1f.png", object.rating];
UIImage *ratingsImage = [UIImage imageNamed:ratingImageName];
if (ratingsImage) {
self.ratingImageView.image = ratingsImage;
}
if (object.imageUrl) {
[self.thumbnailImageView setImageWithURL:[NSURL URLWithString:object.imageUrl] completed:nil];
}
}
@"|[_thirdPartyAnswerView]-38-|"
Je ne comprends toujours pas pourquoi le libellé ne s'affiche pas de nouveau après la mise à jour de la taille de la vue parent lorsque celle-ci comporte des contraintes de début et de fin.
Voir la réponse de Matt ci-dessous: https://stackoverflow.com/a/15514707/287403
Au cas où vous ne liriez pas le commentaire, le principal problème était que je configurais inconsciemment preferredMaxLayoutWidth
via IB lorsque je concevais une vue sur une largeur plus grande que celle affichée (dans certains cas). preferredMaxLayoutWidth
est ce qui est utilisé pour déterminer où le texte est renvoyé. Ainsi, même si ma vue et titleLabel ont été correctement redimensionnés, la variable preferredMaxLayoutWidth
était toujours à l’ancienne valeur et entraînait un retour à la ligne à des points inattendus. En définissant plutôt titleLabel sur sa taille automatique (= dans IB), et la mise à jour de la variable preferredMaxLayoutWidth
de manière dynamique dans layoutSubviews
avant d'appeler super était la clé. Merci Matt!
Je suis quelqu'un qui a écrit une application qui utilise la suppression automatique de cinq étiquettes dans une cellule d'un tableau dont les cellules ont des hauteurs différentes. Je vais donc suggérer que la raison pour laquelle vous rencontrez des problèmes est peut-être que vos contraintes sous-déterminent la présentation, c'est-à-dire que vous avez une disposition ambiguë des éléments de la cellule. Je ne peux pas tester cette hypothèse car je ne vois pas vos contraintes. Mais vous pouvez facilement vérifier (je pense) en utilisant po [[UIWindow keyWindow] _autolayoutTrace]
lorsqu’il est mis en pause dans le débogueur.
J'ai aussi une autre suggestion (désolée de vous lancer des choses): assurez-vous que vous définissez la variable preferredMaxLayoutWidth
de l'étiquette. Ceci est crucial car c'est la largeur à laquelle l'étiquette cessera de croître horizontalement et commencera à croître verticalement.
J'ai eu le même problème et résolu en utilisant une suggestion de cette réponse . Dans une sous-classe de UILabel, j'ai placé ce code:
- (void)layoutSubviews
{
[super layoutSubviews];
self.preferredMaxLayoutWidth = self.bounds.size.width;
}
Je ne comprends pas pourquoi ce n'est pas le comportement par défaut d'UILabel, ou du moins pourquoi vous ne pouvez pas simplement l'activer via un indicateur.
Je suis un peu préoccupé par le fait que preferredMaxLayoutWidth est défini au milieu du processus de présentation, mais je ne vois pas de solution simple à ce problème.
Vérifiez également que vous passez des nombres intégraux à vos contraintes de présentation dans le code.
Pour moi, après quelques calculs (par exemple, convertPoint: toView :), je passais quelque chose comme 23.99999997, ce qui a finalement abouti à une étiquette de 2 lignes s’affichant comme une ligne (si son cadre semblait être calculé correctement) . Dans mon cas, CGRectIntegral a fait le tour!
Les erreurs d'arrondis pourraient te tuer :)