Ich habe ein Problem mit der Einstellung des Eckenradius in der Ansicht, da seit der Xcode-Aktualisierung auf 8 die Rahmen der Ansichten in den meisten Fällen auf 1000x1000 statt der entsprechenden Größe eingestellt sind.
Es gibt eine ähnliche Frage hier , aber ich würde gerne etwas mehr hinzufügen, in der Hoffnung, dass jemand die Antwort gefunden hat oder ein Workaround.
In einer der Instanzen habe ich eine Tabellenansichtszelle, in der eine Bildansicht im Storyboard erstellt wurde. Seine Breite und Höhe werden als Konstante mit Einschränkung (bis 95) festgelegt. Der Eckenradius wird in layoutSubviews
festgelegt, das bisher funktioniert hat:
Also habe ich ein wenig mit Trial and Error herumgespielt und die Situation scheint etwas besser zu laufen, wenn ich versuche, das Layout nach dem Setzen des Bildes auszulösen (ein Bild wird vom Remote-Server abgerufen), indem ich Folgendes anrufe:
%Vor%Das funktioniert in den meisten Fällen immer noch nicht. Jetzt der lustige Teil:
Ich habe einen Fall dieses View-Controllers in der Tab-Leiste, wo ich, wenn ich den Tab mit dem Target-View-Controller drücke, sofort Subviews aufrufen werde (aus UIApplicationMain
), wo die Größe der Image-View 1000x1000 ist Aber sobald das Bild gesetzt ist und ich die Layout-Methoden aufgerufen habe, werden die Layout-Subviews mit der korrekten Bildansichtsgröße von 95x95 erneut aufgerufen, um ein korrektes Ergebnis zu erhalten.
Die zweite Situation ist, dass der View-Controller des gleichen Typs gedrückt wird, bei dem jetzt das Layout nicht zuerst aufgerufen wird, der einzige Aufruf erfolgt, nachdem das Bild gesetzt und das Layout erzwungen wurde. Das Ergebnis ist wieder eine Bildansicht der Größe 1000x1000, wobei der Eckenradius auf 500 eingestellt wird und das Bild nicht sichtbar ist.
Gibt es also eine nette Lösung, um diese seltsamen Rahmenwerte zu korrigieren? Ich habe das gleiche Problem auf mehreren View-Controllern, Tabellenansicht Zellen. Es hat alles bis zum Update funktioniert.
Hat jemand irgendwelche Ideen, was ist die Ursache für dieses Problem überhaupt? Ist es aus dem Storyboard oder eine Art von Einstellungen Migration oder ist dies ein Layout-Fehler mit dieser Version der Software eingeführt?
Ich habe jetzt auch die wake from nib hinzugefügt:
%Vor%Was nun dazu führt, dass das Layout in meinem Fall mindestens zweimal und das zweite Mal korrekt ist. Aber das ist bei weitem nicht die Antwort, das ist schrecklich und ich würde es gerne sehen, da ich es für alle Zellen für die einzelnen Bildansichten verwenden müsste, Buttons.
Ich nehme an, dass die layoutSubviews
Überschreibung, die in der Frage angezeigt wird, eine benutzerdefinierte Unterklasse von UITableViewCell
ist.
Das Problem hier ist wahrscheinlich, dass myImageView
keine direkte Unteransicht der Zelle ist.
Es ist wichtig zu verstehen, dass der Aufruf der Zelle an [super layoutSubviews]
nur die Frames der direkten Subviews der Zelle festlegt. Es geht nicht den ganzen Weg in der Ansichtshierarchie vor der Rückkehr. Die Zelle hat normalerweise nur eine direkte Unteransicht: ihre contentView
. Der Aufruf von [super layoutSubviews]
setzt also nur den Rahmen der Inhaltsansicht und kehrt dann zurück. Der Versuch, self.myImageView.layer.cornerRadius
zu setzen, geschieht zu früh, weil self.myImageView.frame
noch nicht aktualisiert wurde.
Später, nachdem die layoutSubviews
-Methode der Zelle zurückgegeben wurde, sendet UIKit die Nachricht layoutSubviews
an die Inhaltsansicht. Zu diesem Zeitpunkt setzt die Inhaltsansicht ihre eigenen Frames der direkten Unteransicht. Das ist, wenn der Rahmen von myImageView
gesetzt wird.
Die einfachste Lösung besteht darin, eine UIImageView
-Unterklasse zu erstellen und ihre layoutSubviews
zu überschreiben, um ihren eigenen Eckenradius festzulegen.
Matic Oblak fragt (in einem Kommentar): "Ist das, was du hier geschrieben hast, testbar?"?
Ja, es ist testbar. Hier eine Möglichkeit, es zu testen: Erstellen Sie eine Ansichtshierarchie mit einer Stammansicht, einer Containeransicht in der Stammansicht und einer Blattansicht in der Containeransicht:
Überschreibe layoutSubviews
in der Stammansicht und der Containeransicht, um die Rahmen der Ansichten zu drucken:
Sehen wir uns als gutes Beispiel auch an, ob die viewWillLayoutSubviews
und viewDidLayoutSubviews
des View-Controllers ausgeführt werden:
Schließlich führen Sie es auf einem Gerät oder einer Simulation mit einer anderen Größe als im Storyboard aus und schauen Sie sich die Debug-Konsole an:
%Vor% Beachten Sie, dass das [super layoutSubviews]
der Stammansicht den Rahmen der Containeransicht ändert, aber nicht den Rahmen der Blattansicht ändert. Die [super layoutSubviews]
der Containeransicht ändert dann die Größe der Blattansicht.
Wenn layoutSubviews
in einer Ansicht ausgeführt wurde, können Sie daher annehmen, dass die Frames der direkten Untersichten der Ansicht aktualisiert wurden, aber Sie müssen davon ausgehen, dass die Frames von tiefer verschachtelten Ansichten nicht
Beachten Sie auch, dass viewDidLayoutSubviews
ausgeführt wird, nachdem die Ansicht des View-Controllers layoutSubviews
ausgeführt hat, aber vor , dass die tiefer verschachtelten Nachkommen layoutSubviews
ausgeführt haben. In viewDidLayoutSubviews
müssen Sie also erneut davon ausgehen, dass die Frames der tiefer verschachtelten Ansichten nicht aktualisiert wurden.
Es gibt eine Möglichkeit, den Frame einer tief verschachtelten Subview sofort zu aktualisieren: sende layoutIfNeeded
an seine Superview. Zum Beispiel kann ich -[RootView layoutSubviews]
ändern, um layoutIfNeeded
an _leafView.superview
zu senden:
(Beachten Sie, dass in diesem Beispielprojekt _leafView.superview
_containerView
ist, aber im Allgemeinen nicht.) Hier ist das Ergebnis:
Nun habe ich UIKit gezwungen, den Rahmen von _leafView
zu aktualisieren, bevor -[RootView layoutSubviews]
zurückkehrt.
Was "Ich nehme an, viele Operationen wie das Setzen eines einfachen Textes auf dem Etikett wird setNeedsLayout aufrufen": Sie können die gleiche Technik verwenden, die ich gerade demonstriert habe, um die Antwort auf diese Frage herauszufinden.
Ich habe eine Demo-Anwendung erstellt, um zu sehen, welche Mindestanforderungen für dieses Problem erfüllt sind, und es ist ziemlich niedrig:
layoutSubviews
den Eckenradius der Bildansicht auf die Hälfte der Bildansichtsbreite (das Ergebnis wird immer 500 sein) Die Bildansicht wird nicht angezeigt, da der Eckenradius 500 ist.
Also habe ich nach einer minimalen Korrektur gesucht und aus früheren Tests scheint es, dass das Layout den ersten Aufruf nicht enthält, also habe ich es hinzugefügt, indem ich die "wake from nib" überschrieben habe:
%Vor%Also in dem Projekt, an dem ich gerade arbeite, habe ich eine neue Unterklasse einer Tabellenansichtszelle erstellt, und ich habe die "wake from nib" überschrieben. Dann habe ich alle anderen Zellen zu einer Unterklasse gemacht. Es ist keine Lösung, aber es ist ein Workaround, und da ich 57 Tabellenansicht Zelle Unterklassen habe, war diese Prozedur ziemlich schnell zu implementieren.
Wenn Sie nur die @ pushkraj-Antwort für die runde Ansicht hinzufügen, sollten Ihre UIView-Breite und -Höhe gleich sein.
Dann können Sie tun.
%Vor%Versuchen Sie, die drawRect: -Methode in der UIImageView-Unterklasse zu überschreiben und dann den Eckenradius festzulegen.
%Vor%Tags und Links objective-c ios uiview cornerradius