我想補充一下n8gray的回答,在某些情況下,您需要撥打setNeedsLayout
然後layoutIfNeeded
。
比方說,您編寫了一個擴展UIView的自定義視圖,其中子視圖的位置很複雜,無法使用autoresizingMask或iOS6 AutoLayout完成。定製定位可以通過覆蓋layoutSubviews
來完成。
舉個例子,假設您有一個自定義視圖,該視圖具有contentView
屬性和edgeInsets
屬性,該屬性允許設置contentView周圍的邊距。 layoutSubviews
應該是這樣的:
- (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);
}
如果你希望能夠隨時更改edgeInsets
屬性動畫幀的變化,你需要重寫edgeInsets
setter方法如下,並呼籲其次layoutIfNeeded
setNeedsLayout
:
- (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
}
這樣,如果您執行以下操作,如果更改動畫塊內的edgeInsets屬性,則contentView的框架更改將爲動畫。
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
如果不添加調用layoutIfNeeded在setEdgeInsets方法,動畫將無法工作,因爲layoutSubviews將在下一個更新週期,這相當於調用它的動畫塊外調用。
如果只調用setEdgeInsets方法中的layoutIfNeeded,則不會設置setNeedsLayout標誌。
謝謝 - 很高興有人終於回答了這個問題。在此期間,我還必須深入研究setNeedsDisplay - 它會導致drawRect被調用 - 和contentMode。只有contentMode = UIViewContentModeRedraw將導致setNeedsDisplay在視圖邊界更改時被調用。其他contentMode選項只會導致視圖縮放,移動一定量,或者與邊緣對齊。我的自定義UITableViewCell不想重新定位方向更改,它只會縮放,直到我將contentMode設置爲UIViewContentModeRedraw。 – Tarfa 2010-05-29 13:08:05
我想你的代碼中的[self.subview1 layoutSubviews]應該替換爲[self.subview1 setNeedsLayout]。由於layoutSubviews意味着被覆蓋,但並不意味着從另一個視圖調用。框架決定何時調用它(通過將多個佈局請求分組爲一個調用以提高效率),或者通過在視圖層次結構中的某個位置調用layoutIfNeeded來間接執行此操作。 – Tarfa 2010-05-29 13:20:25
更正以上我的評論:「...由於layoutSubviews是意圖被覆蓋或從自己調用,但並不意味着被調用或從另一個視圖...」 – Tarfa 2010-05-29 13:29:01