Lorsque j'ajoute une sous-vue à une UIView
ou que je redimensionne une sous-vue existante, je m'attends à ce que [view sizeToFit]
et [view sizeThatFits]
reflètent ce changement. Cependant, mon expérience est que sizeToFit
ne fait rien et que sizeThatFits
renvoie la même valeur avant et après le changement.
Mon projet de test a une seule vue qui contient un seul bouton. Un clic sur le bouton ajoute un autre bouton à la vue, puis appelle sizeToFit
dans la vue qui le contient. Les limites de la vue sont vidées dans la console avant et après l'ajout de la sous-vue.
- (void) logSizes {
NSLog(@"theView.bounds: %@", NSStringFromCGRect(theView.bounds));
NSLog(@"theView.sizeThatFits: %@", NSStringFromCGSize([theView sizeThatFits:CGSizeZero]));
}
- (void) buttonTouched {
[self logSizes];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(10.0f, 100.0f, 400.0f, 600.0f);
[theView addSubview:btn];
[theView sizeToFit];
[self performSelector:@selector(logSizes) withObject:nil afterDelay:1.0];
}
Et le résultat est:
2010-10-15 15:40:42.359 SizeToFit[14953:207] theView.bounds: {{0, 0}, {322, 240}}
2010-10-15 15:40:42.387 SizeToFit[14953:207] theView.sizeThatFits: {322, 240}
2010-10-15 15:40:43.389 SizeToFit[14953:207] theView.bounds: {{0, 0}, {322, 240}}
2010-10-15 15:40:43.391 SizeToFit[14953:207] theView.sizeThatFits: {322, 240}
Je dois manquer quelque chose ici.
Merci.
La documentation est assez claire à ce sujet. -sizeToFit
appelle à peu près -sizeThatFits:
(probablement avec la taille actuelle de la vue comme argument), et l'implémentation par défaut de -sizeThatFits:
ne fait presque rien (elle ne retourne que son argument).
Certaines sous-classes UIView surchargent -sizeThatFits:
pour faire quelque chose de plus utile (par exemple UILabel). Si vous souhaitez utiliser d'autres fonctionnalités (telles que le redimensionnement d'une vue pour l'adapter à ses sous-vues), vous devez sous-classer UIView et remplacer le -sizeThatFits:
.
Si vous ne voulez pas remplacer UIView, vous pouvez simplement utiliser l'extension.
Rapide:
extension UIView {
func sizeToFitCustom () {
var size = CGSize(width: 0, height: 0)
for view in self.subviews {
let frame = view.frame
let newW = frame.Origin.x + frame.width
let newH = frame.Origin.y + frame.height
if newW > size.width {
size.width = newW
}
if newH > size.height {
size.height = newH
}
}
self.frame.size = size
}
}
Le même code mais 3 fois plus vite:
extension UIView {
final func sizeToFitCustom() {
var w: CGFloat = 0,
h: CGFloat = 0
for view in subviews {
if view.frame.Origin.x + view.frame.width > w { w = view.frame.Origin.x + view.frame.width }
if view.frame.Origin.y + view.frame.height > h { h = view.frame.Origin.y + view.frame.height }
}
frame.size = CGSize(width: w, height: h)
}
}
self.errorMessageLabel.text = someNewMessage;
// We don't know how long the given error message might be, so let's resize the label + containing view accordingly
CGFloat heightBeforeResize = self.errorMessageLabel.frame.size.height;
[self.errorMessageLabel sizeToFit];
CGFloat differenceInHeightAfterResize = self.errorMessageLabel.frame.size.height - heightBeforeResize;
self.errorViewHeightContstraint.constant = kErrorViewHeightConstraintConstant + differenceInHeightAfterResize;
Cela a fonctionné pour moi.
Vous pouvez en faire comme ça en utilisant IB seul (xcode 4.5):
UIView
content hugging
vers 1 (horizontal et vertical)compression resistance
vers 1000 (pour les deux)constraints
, cliquez sur Width
et changez priority
en 250UIView
's inset
pour contrôler le remplissage pour gauche/droite/haut/bas