ฉันต้องการเพิ่มคำตอบของ 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
ตั้งค่าดังต่อไปนี้และเรียกsetNeedsLayout
ตามด้วย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
}
ด้วยวิธีนี้หากคุณทำสิ่งต่อไปนี้หากคุณเปลี่ยนคุณสมบัติ edgeInsets ภายในบล็อกแอนิเมชั่นการเปลี่ยนเฟรมของ contentView จะเป็นแบบเคลื่อนไหว
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
หากคุณไม่ได้เพิ่มการเรียกไปยัง layoutIfNeeded ในเมธอด setEdgeInsets ภาพเคลื่อนไหวจะไม่ทำงานเนื่องจาก layoutSubviews จะถูกเรียกในรอบการอัปเดตถัดไปซึ่งเท่ากับการเรียกมันนอกบล็อกภาพเคลื่อนไหว
ถ้าคุณเรียกใช้เฉพาะ layoutIfNeeded ในเมธอด setEdgeInsets จะไม่มีอะไรเกิดขึ้นเนื่องจากไม่ได้ตั้งค่าแฟล็ก setNeedsLayout