Ich spreche nicht über die Frame-Eigenschaft, da Sie daraus nur die Größe der Ansicht in der xib erhalten können. Ich spreche davon, wann die Größe der Ansicht aufgrund ihrer Einschränkungen geändert wird (möglicherweise nach einer Drehung oder als Reaktion auf ein Ereignis). Gibt es eine Möglichkeit, die aktuelle Breite und Höhe zu ermitteln?
Ich habe versucht, die Einschränkungen zu durchlaufen, um nach Einschränkungen für Breite und Höhe zu suchen, aber das ist nicht sehr sauber und schlägt fehl, wenn es intrinsische Einschränkungen gibt (da ich nicht zwischen den beiden unterscheiden kann). Dies funktioniert auch nur, wenn sie tatsächlich Einschränkungen für Breite und Höhe haben, was sie nicht tun, wenn sie sich beim Ändern der Größe auf andere Einschränkungen verlassen.
Warum ist das so schwierig für mich? ARG!
quelle
Antworten:
Die Antwort lautet
[view layoutIfNeeded]
.Hier ist der Grund:
Sie erhalten weiterhin die aktuelle Breite und Höhe der Ansicht, indem Sie
view.bounds.size.width
undview.bounds.size.height
(oder den Rahmen, der gleichwertig ist, sofern Sie nicht mit dem spielenview.transform
) überprüfen .Wenn Sie die Breite und Höhe wünschen, die durch Ihre vorhandenen Einschränkungen impliziert werden, besteht die Antwort nicht darin, die Einschränkungen manuell zu überprüfen, da Sie dazu die gesamte Logik zur Lösung von Einschränkungen des automatischen Layoutsystems erneut implementieren müssten, um diese zu interpretieren Einschränkungen. Stattdessen sollten Sie nur das automatische Layout bitten, dieses Layout zu aktualisieren , damit es die Einschränkungen löst und den Wert von view.bounds mit der richtigen Lösung aktualisiert. Anschließend überprüfen Sie die view.bounds.
Wie können Sie das automatische Layout bitten, das Layout zu aktualisieren? Rufen
[view setNeedsLayout]
Sie an, wenn das automatische Layout das Layout in der nächsten Runde der Run-Schleife aktualisieren soll.Allerdings , wenn Sie wollen , dass es das Layout sofort aktualisieren, so können Sie sofort die neuen Grenzen Zugriff Wert später im aktuellen Funktion oder an einem anderen Punkt vor der Wende der Laufschleife, dann müssen Sie anrufen
[view setNeedsLayout]
und[view layoutIfNeeded]
.Sie haben eine zweite Frage gestellt: "Wie kann ich eine Höhen- / Breitenbeschränkung ändern, wenn ich keinen direkten Verweis darauf habe?".
Wenn Sie die Einschränkung in IB erstellen, besteht die beste Lösung darin, ein IBOutlet in Ihrem Ansichtscontroller oder Ihrer Ansicht zu erstellen, damit Sie einen direkten Verweis darauf haben. Wenn Sie die Einschränkung im Code erstellt haben, sollten Sie zum Zeitpunkt der Erstellung eine Referenz in einer internen schwachen Eigenschaft beibehalten. Wenn jemand anderes die Einschränkung erstellt hat, müssen Sie sie finden, indem Sie die Eigenschaft view.constraints in der Ansicht und möglicherweise die gesamte Ansichtshierarchie untersuchen und eine Logik implementieren, die die entscheidende NSLayoutConstraint findet. Dies ist wahrscheinlich der falsche Weg, da Sie auch effektiv bestimmen müssen, welche bestimmte Einschränkung die Grenzgröße bestimmt, wenn nicht garantiert wird, dass eine einfache Antwort auf diese Frage vorliegt. Der endgültige Grenzwert könnte die Lösung für ein sehr kompliziertes System mit mehreren Einschränkungen sein.
quelle
layoutIfNeeded
ist großartig und macht den Rahmen sofort verfügbar. Es wird jedoch auch das Rendern der Einschränkungen für alle Ansichten in den Unterbäumen der Ansicht erzwingen, für die es aufgerufen wird. Wenn Sie beispielsweise Ansichten programmgesteuert hinzufügen undlayoutIfNeeded
alle in Ihrer rekursiven Routine aufrufen , wird Ihre Ansichtshierarchie möglicherweise sehr langsam gerendert. (Ich habe das auf die harte Tour gelernt.) Wie in der hervorragenden Antwort erwähnt, ist 'setNeedsLayout' effizienter und stellt den Frame beim nächsten Layoutdurchlauf zur Verfügung, was idealerweise in etwa 1/60 Sekunde geschieht.initWithCoder
?Ich hatte ein ähnliches Problem, bei dem ich einen oberen und unteren Rand zu einem
UITableView
hinzufügen musste, dessen Größe basierend auf den in der Einrichtung festgelegten Einschränkungen geändert wurdeUIStoryboard
. Ich konnte mit auf die aktualisierten Einschränkungen zugreifen- (void)viewDidLayoutSubviews
. Dies ist nützlich, damit Sie eine Ansicht nicht unterordnen und ihre Layoutmethode überschreiben müssen.Ohne die Methode von der Methode aus aufzurufen
viewDidLayoutSubview
, wird nur der obere Rand korrekt gezeichnet, da sich der untere Rand irgendwo außerhalb des Bildschirms befindet.quelle
[super viewDidLayoutSubviews];
Für diejenigen, die möglicherweise noch mit solchen Problemen konfrontiert sind, insbesondere mit TableviewCell.
Überschreiben Sie einfach die Methode:
Bei UITableViewCell oder UICollectionViewCell erstellen Sie eine Unterklasse der Zelle und überschreiben dieselbe Methode:
quelle
Verwenden
-(void)viewWillAppear:(BOOL)animated
und anrufen[self.view layoutIfNeeded];
- Es funktioniert, ich habe versucht.Denn wenn Sie es verwenden
-(void)viewDidLayoutSubviews
, wird es definitiv funktionieren, aber diese Methode wird jedes Mal aufgerufen, wenn Ihre Benutzeroberfläche Aktualisierungen / Änderungen erfordert. Welches wird schwer zu verwalten sein. Softkey ist, dass Sie eine Bool-Variable verwenden, um eine solche Aufrufschleife zu vermeiden. bessere VerwendungviewWillAppear
. RememberviewWillAppear
wird auch aufgerufen, wenn die Ansicht wieder geladen wird (ohne Neuzuweisung).quelle
Der Rahmen ist noch gültig. Am Ende verwendet die Ansicht ihre Rahmeneigenschaft, um sich selbst zu gestalten. Dieser Frame wird basierend auf allen Einschränkungen berechnet. Die Einschränkungen werden nur für das anfängliche Layout verwendet (und jedes Mal, wenn layoutSubviews in einer Ansicht wie nach einer Drehung aufgerufen wird). Danach befinden sich die Positionsinformationen in der Frame-Eigenschaft. Oder siehst du etwas anderes?
quelle