L'API correcte à utiliser est UIView systemLayoutSizeFittingSize:
, en passant soit UILayoutFittingCompressedSize
ou UILayoutFittingExpandedSize
.
Pour une mise UIView
en page automatique normale, cela devrait fonctionner tant que vos contraintes sont correctes. Si vous souhaitez l'utiliser sur un UITableViewCell
(pour déterminer la hauteur de ligne par exemple), vous devez l'appeler contre votre cellule contentView
et saisir la hauteur.
D'autres considérations existent si vous avez un ou plusieurs UILabel dans votre vue qui sont multilignes. Pour ceux-ci, il est impératif que la preferredMaxLayoutWidth
propriété soit correctement définie de sorte que l'étiquette fournisse un correct intrinsicContentSize
, qui sera utilisé dans le systemLayoutSizeFittingSize's
calcul.
EDIT: sur demande, ajout d'un exemple de calcul de hauteur pour une cellule de vue tableau
L'utilisation de la disposition automatique pour le calcul de la hauteur des cellules d'un tableau n'est pas très efficace, mais elle est certainement pratique, surtout si vous avez une cellule qui a une disposition complexe.
Comme je l'ai dit ci-dessus, si vous utilisez une multiligne, UILabel
il est impératif de synchroniser le preferredMaxLayoutWidth
avec la largeur de l'étiquette. J'utilise une UILabel
sous-classe personnalisée pour ce faire:
@implementation TSLabel
- (void) layoutSubviews
{
[super layoutSubviews];
if ( self.numberOfLines == 0 )
{
if ( self.preferredMaxLayoutWidth != self.frame.size.width )
{
self.preferredMaxLayoutWidth = self.frame.size.width;
[self setNeedsUpdateConstraints];
}
}
}
- (CGSize) intrinsicContentSize
{
CGSize s = [super intrinsicContentSize];
if ( self.numberOfLines == 0 )
{
// found out that sometimes intrinsicContentSize is 1pt too short!
s.height += 1;
}
return s;
}
@end
Voici une sous-classe UITableViewController artificielle démontrant heightForRowAtIndexPath:
#import "TSTableViewController.h"
#import "TSTableViewCell.h"
@implementation TSTableViewController
- (NSString*) cellText
{
return @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
}
#pragma mark - Table view data source
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView
{
return 1;
}
- (NSInteger) tableView: (UITableView *)tableView numberOfRowsInSection: (NSInteger) section
{
return 1;
}
- (CGFloat) tableView: (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath
{
static TSTableViewCell *sizingCell;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sizingCell = (TSTableViewCell*)[tableView dequeueReusableCellWithIdentifier: @"TSTableViewCell"];
});
// configure the cell
sizingCell.text = self.cellText;
// force layout
[sizingCell setNeedsLayout];
[sizingCell layoutIfNeeded];
// get the fitting size
CGSize s = [sizingCell.contentView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize];
NSLog( @"fittingSize: %@", NSStringFromCGSize( s ));
return s.height;
}
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
{
TSTableViewCell *cell = (TSTableViewCell*)[tableView dequeueReusableCellWithIdentifier: @"TSTableViewCell" ];
cell.text = self.cellText;
return cell;
}
@end
Une simple cellule personnalisée:
#import "TSTableViewCell.h"
#import "TSLabel.h"
@implementation TSTableViewCell
{
IBOutlet TSLabel* _label;
}
- (void) setText: (NSString *) text
{
_label.text = text;
}
@end
Et voici une image des contraintes définies dans le Storyboard. Notez qu'il n'y a pas de contraintes de hauteur / largeur sur l'étiquette - celles-ci sont déduites des étiquettes intrinsicContentSize
: