Tôi muốn thêm vào câu trả lời của n8gray rằng trong một số trường hợp, bạn sẽ cần phải gọi setNeedsLayout
theo sau layoutIfNeeded
.
Ví dụ: giả sử bạn đã viết một chế độ xem tùy chỉnh mở rộng UIView, trong đó việc định vị các chế độ xem phụ rất phức tạp và không thể thực hiện được với autoresizingMask hoặc iOS6 AutoLayout. Định vị tùy chỉnh có thể được thực hiện bằng cách ghi đè layoutSubviews
.
Ví dụ: giả sử bạn có một chế độ xem tùy chỉnh có một thuộc contentView
tính và một thuộc edgeInsets
tính cho phép đặt lề xung quanh contentView. layoutSubviews
sẽ trông như thế này:
- (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);
}
Nếu bạn muốn có thể tạo hiệu ứng thay đổi khung hình bất cứ khi nào bạn thay đổi thuộc edgeInsets
tính, bạn cần ghi đè bộ cài edgeInsets
đặt như sau và gọi setNeedsLayout
theo sau 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
}
Theo cách đó, nếu bạn làm như sau, nếu bạn thay đổi thuộc tính edgeInsets bên trong một khối hoạt ảnh, thì sự thay đổi khung của contentView sẽ được làm động.
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
Nếu bạn không thêm lệnh gọi layoutIfNeeded trong phương thức setEdgeInsets, hoạt ảnh sẽ không hoạt động vì layoutSubviews sẽ được gọi vào chu kỳ cập nhật tiếp theo, tương đương với việc gọi nó bên ngoài khối hoạt ảnh.
Nếu bạn chỉ gọi layoutIfNeeded trong phương thức setEdgeInsets, sẽ không có gì xảy ra khi cờ setNeedsLayout không được đặt.