web-dev-qa-db-fra.com

Avoir du mal à faire en sorte que UIView sizeToFit fasse quelque chose de significatif

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.

35
FishesCycle

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

49
Ole Begemann

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. 

0
shaunlim

Vous pouvez en faire comme ça en utilisant IB seul (xcode 4.5):

  1. Cliquez sur la UIView
  2. dans l'inspecteur de taille, faites glisser content hugging vers 1 (horizontal et vertical)
  3. faites glisser compression resistance vers 1000 (pour les deux)
  4. sous UIView's constraints, cliquez sur Width et changez priority en 250
  5. Faites de même pour la hauteur
  6. Vous pouvez utiliser la UIView 's inset pour contrôler le remplissage pour gauche/droite/haut/bas
0
marmor