Ich möchte hinzufügen, n8gray die Antwort, dass in einigen Fällen müssen Sie setNeedsLayout
gefolgt von layoutIfNeeded
aufrufen.
Nehmen wir an, Sie haben beispielsweise eine benutzerdefinierte Ansicht geschrieben, die UIView erweitert, in der die Positionierung von Unteransichten komplex ist und nicht mit autoresizingMask oder iOS6 AutoLayout durchgeführt werden kann. Die benutzerdefinierte Positionierung kann durch Überschreiben layoutSubviews
vorgenommen werden.
Angenommen, Sie haben eine benutzerdefinierte Ansicht mit einer contentView
-Eigenschaft und einer edgeInsets
-Eigenschaft, mit der Sie die Ränder um die contentView herum festlegen können. layoutSubviews
würde wie folgt aussehen:
- (void) layoutSubviews {
self.contentView.frame = CGRectMake(
self.bounds.origin.x + self.edgeInsets.left,
self.bounds.origin.y + self.edgeInsets.top,
self.bounds.size.width - self.edgeInsets.left - self.edgeInsets.right,
self.bounds.size.height - self.edgeInsets.top - self.edgeInsets.bottom);
}
Wenn Sie den Bildwechsel in der Lage sein wollen, animieren, wenn Sie die edgeInsets
Eigenschaft zu ändern, müssen Sie die edgeInsets
Setter außer Kraft zu setzen wie folgt und rufen setNeedsLayout
gefolgt von layoutIfNeeded
:
- (void) setEdgeInsets:(UIEdgeInsets)edgeInsets {
_edgeInsets = edgeInsets;
[self setNeedsLayout]; //Indicates that the view needs to be laid out
//at next update or at next call of layoutIfNeeded,
//whichever comes first
[self layoutIfNeeded]; //Calls layoutSubviews if flag is set
}
Wenn Sie folgendermaßen vorgehen, wenn Sie die EdgeInsets -Eigenschaft innerhalb eines Animationsblocks ändern, wird der Rahmenwechsel der ContentView animiert.
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
Wenn Sie den Anruf nicht zu layoutIfNeeded im setEdgeInsets Methode hinzufügen, wird die Animation nicht funktionieren, weil die layoutSubviews wird beim nächsten Update-Zyklus aufgerufen, die es außerhalb des Animationsblocks Aufruf entspricht.
Wenn Sie in der setEdgeInsets-Methode nur layoutIfNeeded aufrufen, geschieht nichts, da das Flag setNeedsLayout nicht gesetzt ist.
Danke - froh, dass jemand endlich das beantwortet hat. In der Zwischenzeit musste ich mich auch mit setNeedsDisplay - was bewirkt, dass drawRect aufgerufen wird - und contentMode beschäftigen. Nur contentMode = UIViewContentModeRedraw bewirkt, dass setNeedsDisplay aufgerufen wird, wenn sich die Grenzen einer Ansicht ändern. Die anderen contentMode-Optionen bewirken nur, dass die Ansicht skaliert, um einen bestimmten Betrag verschoben oder an einer Kante ausgerichtet wird. Mein benutzerdefiniertes UITableViewCell wollte bei Orientierungsänderungen nicht neu zeichnen, es würde nur skalieren, bis ich contentMode auf UIViewContentModeRedraw setze. – Tarfa
Ich denke, dass die [selfview1 layoutSubviews] in Ihrem Code durch [selfview1 setNeedsLayout] ersetzt werden sollte. Da layoutSubviews überschrieben werden soll, aber nicht von oder zu einer anderen Ansicht aufgerufen werden soll. Entweder bestimmt das Framework, wann es aufgerufen werden soll (indem mehrere Layoutanfragen in einem Aufruf zur Effizienz zusammengefasst werden), oder Sie tun dies indirekt, indem Sie layoutIfNeeded irgendwo in der Ansichtshierarchie aufrufen. – Tarfa
Korrektur zu meinem obigen Kommentar: "... da layoutSubviews dazu gedacht ist, überschrieben oder von selbst aufgerufen zu werden, aber nicht von oder zu einer anderen Ansicht aufgerufen werden soll ..." – Tarfa