2010-10-15 19 views
35

Lorsque j'ajoute une sous-vue à un UIView, ou lorsque je redimensionne une sous-vue existante, je m'attendrais à ce que [view sizeToFit] et [view sizeThatFits] reflètent cette modification. Cependant, mon expérience est que sizeToFit ne fait rien, et sizeThatFits renvoie la même valeur avant et après le changement.J'ai du mal à faire en sorte que UIView sizeToFit fasse quelque chose de significatif

Mon projet de test a une seule vue contenant un seul bouton. Cliquer sur le bouton ajoute un autre bouton à la vue, puis appelle sizeToFit dans la vue contenant. Les limites de la vue sont déversées sur 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 la sortie 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.

Merci.

Répondre

48

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 renvoie juste son argument).

Certaines sous-classes UIView remplacent -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 -sizeThatFits:.

+1

Merci Ole. Vous devriez avoir lu les documents de plus près plutôt que d'examiner les extraits de code qui reposaient sur le comportement surchargé dans une sous-classe particulière de UIView. – FishesCycle

+2

Je suis surpris qu'il n'y ait pas de réponse ici qui partage leur implémentation d'un tel override. – aleclarson

0

Vous pouvez faire un peu comme en utilisant IB seul (Xcode 4.5):

  1. Cliquez sur le UIView
  2. dans l'inspecteur Taille glisser content hugging-1 (horizontale et verticale)
  3. glisser compression resistance à 1000 (pour les deux)
  4. sous constraints cliquez sur le UIView Width et changer priority-250
  5. Faites de même pour la hauteur
  6. Vous pouvez utiliser pour contrôler le rembourrage pour/haut/bas gauche/droite
0
 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 de inset le UIView.

3

Si vous ne surchargez pas UIView, vous pouvez simplement utiliser l'extension.

Swift:

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 rapide:

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) 
    } 
}