AutoLayout lier deux UILabels pour avoir la même taille de police

J'ai deux UILabels l'un à côté de l'autre dans la rangée avec des ajustements de gauche et de droite de sorte que cela ressemble à ci-dessous.

|-Some text left adjusted----------some other text right adjusted-| 

Les deux labels ont ajustéFontSizeToFitWidth = YES et sont liés les uns aux autres avec la contrainte suivante

 [NSLayoutConstraint constraintWithItem:_rightLabel atsortingbute:NSLayoutAtsortingbuteLeft relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:_leftLabel atsortingbute:NSLayoutAtsortingbuteRight multiplier:1 constant:10] 

Afin qu'ils prennent autant d'espace que possible et s'il n'y a pas assez d'espace pour la taille de la police d'origine, il sera réduit grâce à ajustsFontSizeToFitWidth afin qu'aucun text ne soit tronqué.

Mon problème est que quand on a besoin de réduire sa taille de police en raison du text long je veux que l'autre label réduise sa taille de police ainsi que les deux aient la même taille au lieu d'un peut être deux fois la taille de l'autre. Je voudrais contraindre la taille de police aussi bien pour faire correspondre mais hélas je ne sais pas comment ceci, aucune idée?

Dans la documentation de adjustsFontSizeToWidth sur adjustsFontSizeToWidth :

Normalement, le text de l'label est dessiné avec la police que vous spécifiez dans la propriété de police. Toutefois, si cette propriété est définie sur YES et que le text de la propriété text dépasse le rectangle englobant de l'label, le récepteur commence à réduire la taille de la police jusqu'à ce que la string soit ajustée ou que la taille de police minimale soit atteinte.

J'en déduis que la police mise à jour est calculée au moment du dessin, et que la propriété de font est seulement lue, non écrite. Par conséquent, je crois que la suggestion d'Andrew d'utiliser KVO sur la propriété de font ne fonctionnera pas.

Par conséquent, pour get le résultat souhaité, vous devez calculer la taille de police ajustée.

Comme le note Jackson dans les commentaires, cette méthode NSSsortingng très pratique pour get la police réelle a été obsolète dans iOS 7. Techniquement, vous pouvez toujours l'utiliser jusqu'à ce qu'il soit supprimé.

Une autre alternative consiste à faire défiler les échelles de fonts jusqu'à ce que vous en trouviez une qui convienne aux deux labels. J'ai réussi à le faire fonctionner correctement; Voici un exemple de projet qui montre comment je l'ai fait .

En outre, voici le code au cas où ce lien cesse de fonctionner:

 - (void)viewDidLoad { [super viewDidLoad]; NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:_rightLabel atsortingbute:NSLayoutAtsortingbuteLeft relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:_leftLabel atsortingbute:NSLayoutAtsortingbuteRight multiplier:1 constant:10]; [self.view addConstraint:constraint]; } - (IBAction)makeRightLabelLongerPressed:(id)sender { self.rightLabel.text = @"some much longer right label text"; } - (IBAction)adjustLabelSizes:(id)sender { NSLog(@"Attempting to adjust label sizes…"); CGFloat minimumScaleFactor = fmaxf(self.rightLabel.minimumScaleFactor, self.leftLabel.minimumScaleFactor);; UIFont * startingFont = self.rightLabel.font; for (double currentScaleFactor = 1.0; currentScaleFactor > minimumScaleFactor; currentScaleFactor -= 0.05) { UIFont *font = [startingFont fontWithSize:startingFont.pointSize * currentScaleFactor]; NSLog(@" Attempting font with scale %f (size = %f)…", currentScaleFactor, font.pointSize); BOOL leftLabelWorks = [self wouldThisFont:font workForThisLabel:self.leftLabel]; BOOL rightLabelWorks = [self wouldThisFont:font workForThisLabel:self.rightLabel]; if (leftLabelWorks && rightLabelWorks) { NSLog(@" It fits!"); self.leftLabel.font = font; self.rightLabel.font = font; return; } else { NSLog(@" It didn't fit. :-("); } } NSLog(@" It won't fit without violating the minimum scale (%f), so set both to minimum. Some text may get truncated.", minimumScaleFactor); UIFont *minimumFont = [self.rightLabel.font fontWithSize:self.rightLabel.font.pointSize * self.rightLabel.minimumScaleFactor]; self.rightLabel.font = minimumFont; self.leftLabel.font = minimumFont; } - (BOOL) wouldThisFont:(UIFont *)testFont workForThisLabel:(UILabel *)testLabel { NSDictionary *atsortingbutes = [NSDictionary dictionaryWithObjectsAndKeys:testFont, NSFontAtsortingbuteName, nil]; NSAtsortingbutedSsortingng *as = [[NSAtsortingbutedSsortingng alloc] initWithSsortingng:testLabel.text atsortingbutes:atsortingbutes]; CGRect bounds = [as boundingRectWithSize:CGSizeMake(CGRectGetWidth(testLabel.frame), CGFLOAT_MAX) options:(NSSsortingngDrawingUsesLineFragmentOrigin) context:nil]; BOOL itWorks = [self doesThisSize:bounds.size fitInThisSize:testLabel.bounds.size]; return itWorks; } - (BOOL)doesThisSize:(CGSize)aa fitInThisSize:(CGSize)bb { if ( aa.width > bb.width ) return NO; if ( aa.height > bb.height ) return NO; return YES; } 

Cette approche pourrait être sortingvialement refactorisée en une méthode de catégorie qui remplace la méthode obsolète liée à par Jackson.

J'ai trouvé une meilleure solution. Ajoutez juste à vos espaces de text du début à la fin de uilabel, qui ont less de longueur de text. Et la police sera la même.

Vous pouvez essayer d'utiliser l' observation de valeur-key pour observer les modifications de la propriété de police sur une label et, le cas échéant, définir l'autre label pour utiliser la même police.

Dans votre méthode -viewDidLoad :

 // Add self as an observer of _rightLabel's font property [_rightLabel addObserver:self forKeyPath:@"font" options:NSKeyValueObservingOptionNew context:NULL]; 

Dans la même implémentation de controller (auto dans le context des extraits de code ci-dessus):

 // Observe changes to the font property of _rightLabel - (void)observeValueForKeyPath:(NSSsortingng *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (object == _rightLabel && [keyPath isEqualToSsortingng:@"font"]) { // Set _leftLabel's font property to be the new value set on _rightLabel _leftLabel.font = change[NSKeyValueChangeNewKey]; } }