Frage Gibt es ein UIView-Größenänderungsereignis?


Ich habe eine Ansicht mit Zeilen und Spalten von Bildansichten.

Wenn die Größe dieser Ansicht geändert wird, muss die Position der Bildansichten neu angeordnet werden.

Diese Ansicht ist eine Unteransicht einer anderen Ansicht, deren Größe geändert wird.

Gibt es eine Möglichkeit, festzustellen, wenn diese Ansicht in der Größe geändert wird?


75
2017-10-22 20:21


Ursprung


Antworten:


Wie Uli unten kommentierte, ist der richtige Weg dies zu tun layoutSubviews und layout die imageViews dort.

Wenn Sie aus irgendeinem Grund nicht unterklassifizieren und überschreiben können layoutSubviewsbeobachten bounds sollte funktionieren, auch wenn es irgendwie schmutzig ist. Noch schlimmer, es besteht ein Risiko beim Beobachten - Apple garantiert nicht, dass KVO in UIKit-Klassen funktioniert. Lesen Sie die Diskussion mit Apple Engineer hier: Wann wird ein zugehöriges Objekt freigegeben?

ursprüngliche Antwort:

Sie können die Schlüsselwertbeobachtung verwenden:

[yourView addObserver:self forKeyPath:@"bounds" options:0 context:nil];

und implementieren:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (object == yourView && [keyPath isEqualToString:@"bounds"]) {
        // do your stuff, or better schedule to run later using performSelector:withObject:afterDuration:
    }
}

82
2017-10-22 20:38



In einem UIView Unterklasse, Immobilienbeobachter kann verwendet werden:

override var bounds: CGRect {
    didSet {
        // ...
    }
}

Ohne Unterklassen, Schlüssel-Wert-Beobachtung mit intelligente Schlüsselpfade Wird besorgt:

var boundsObservation: NSKeyValueObservation?

func beginObservingBounds() {
    boundsObservation = observe(\.bounds) { capturedSelf, _ in
        // ...
    }
}

63
2017-12-21 15:41



Erstellen Sie die Unterklasse von UIView und überschreiben Sie layoutSubviews


26
2018-02-15 11:53



Sie können eine Unterklasse von UIView erstellen und die Unterklasse überschreiben

setFrame: (CGRect) Rahmen

Methode. Dies ist die Methode, die aufgerufen wird, wenn der Rahmen (d. H. Die Größe) der Ansicht geändert wird. Tun Sie etwas wie folgt:

- (void) setFrame:(CGRect)frame
{
  // Call the parent class to move the view
  [super setFrame:frame];

  // Do your custom code here.
}

6
2018-05-04 18:18



Ziemlich alt, aber immer noch eine gute Frage. In Apples Beispielcode und in einigen ihrer privaten UIView-Unterklassen überschreiben sie setBounds grob wie folgt:

-(void)setBounds:(CGRect)newBounds {
    BOOL const isResize = !CGSizeEqualToSize(newBounds.size, self.bounds.size);
    if (isResize) [self prepareToResizeTo:newBounds.size]; // probably saves 
    [super setBounds:newBounds];
    if (isResize) [self recoverFromResizing];
}

Überschreiben setFrame: ist keine gute Idee. frame ist abgeleitet von center, bounds, und transform, also iOS wird nicht unbedingt anrufen setFrame:.


6
2018-04-24 18:39



Swift 4 keypath KVO - So erkenne ich die automatische Drehung und den Wechsel zum iPad Side Panel. Sollte Arbeit funktionieren, keine Aussicht. Musste die UIView-Ebene beobachten.

private var observer: NSKeyValueObservation?

override func viewDidLoad() {
    super.viewDidLoad()
    observer = view.layer.observe(\.bounds) { object, _ in
        print(object.bounds)
    }
    // ...
}
override func viewWillDisappear(_ animated: Bool) {
    observer?.invalidate()
    //...
}

5
2017-12-06 22:46



Wenn Sie in einer UIViewController-Instanz sind, überschreiben Sie sie viewDidLayoutSubviews macht den Trick.

override func viewDidLayoutSubviews() {
    // update subviews
}

-3
2018-04-21 05:44