it-swarm.com.de

Sie haben Schwierigkeiten, UIView sizeToFit dazu zu bringen, alles sinnvoll zu machen

Wenn ich einer UIView eine Unteransicht hinzufüge oder eine vorhandene Unteransicht skaliere, würde ich erwarten, dass [view sizeToFit] und [view sizeThatFits] diese Änderung widerspiegeln. Meine Erfahrung ist jedoch, dass sizeToFit nichts tut und sizeThatFits vor und nach der Änderung denselben Wert zurückgibt.

Mein Testprojekt hat eine einzelne Ansicht, die eine einzelne Schaltfläche enthält. Durch Klicken auf die Schaltfläche wird der Ansicht eine weitere Schaltfläche hinzugefügt, und anschließend wird sizeToFit in der enthaltenden Ansicht aufgerufen. Die Begrenzungen der Ansicht werden vor und nach dem Hinzufügen der Unteransicht auf der Konsole ausgegeben.

- (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];
}

Und die Ausgabe ist:

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}

Mir muss hier etwas fehlen.

Vielen Dank.

35
FishesCycle

Die Dokumentation ist diesbezüglich ziemlich klar. -sizeToFit ruft so ziemlich -sizeThatFits: (wahrscheinlich mit der aktuellen Größe der Ansicht als Argument) auf, und die Standardimplementierung von -sizeThatFits: bewirkt fast nichts (sie gibt nur ihr Argument zurück).

Einige UIView-Unterklassen überschreiben -sizeThatFits:, um etwas nützlicheres zu tun (z. B. UILabel). Wenn Sie eine andere Funktionalität wünschen (z. B. die Größe einer Ansicht an ihre Unteransichten anpassen), sollten Sie die Unterklasse UIView und -sizeThatFits: überschreiben.

49
Ole Begemann

Wenn Sie UIView nicht überschreiben, können Sie einfach die Erweiterung verwenden.

Schnell:

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
    }

}

Derselbe Code, jedoch dreimal schneller:

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;

Das hat für mich funktioniert. 

0
shaunlim

Sie können so etwas mit IB alleine machen (xcode 4.5):

  1. Klicken Sie auf die UIView
  2. ziehen Sie im Größeninspektor content hugging auf 1 (sowohl horizontal als auch vertikal).
  3. compression resistance auf 1000 ziehen (für beide)
  4. klicken Sie unter UIView constraints auf Width und ändern Sie priority in 250
  5. Machen Sie dasselbe für Höhe
  6. Sie können die UIView von inset verwenden, um die Auffüllung für links/rechts/oben/unten zu steuern
0
marmor