2013-06-17 34 views
36

Tôi có một lớp con UIView vẽ một vòng tròn có bán kính thay đổi (với hình động bouncy đẹp). Chế độ xem đang quyết định kích thước của vòng tròn.Animate intrinsicContentSize changes

Tôi muốn lớp con UIView này thay đổi kích thước khung hình của nó để khớp với các thay đổi động với bán kính vòng tròn và tôi muốn những thay đổi này sửa đổi bất kỳ NSLayoutConstraints nào được kết nối với chế độ xem (để chế độ xem bị ràng buộc với cạnh của vòng tròn sẽ di chuyển khi vòng tròn thay đổi kích thước).

Tôi hiểu rằng việc triển khai -(CGSize)intrinsicContentSize và gọi invalidateIntrinsicContentSize khi thay đổi bán kính sẽ cho biết các ràng buộc để cập nhật, nhưng tôi không thể tìm ra cách tạo hiệu ứng thay đổi cho intrinsicContentSize.

Gọi invalidateIntrinsicContentSize từ bên trong khối [UIView animateWith ... ngay lập tức cập nhật bố cục.

Điều này có thể thực hiện được và có cách tiếp cận giải pháp tốt hơn không?

+0

Tôi có cảm giác rằng điều này là không thể. Lấy ví dụ về 'UILabel' của nó' intrinsicContentSize' là một hàm của kích thước phông chữ của nó. Tuy nhiên không có cách nào tốt đẹp để tạo hiệu ứng thay đổi phông chữ. Cách giải quyết cho nhãn là làm thay đổi biến đổi của lớp của nó (sử dụng 'CAAnimation') rồi thay đổi phông chữ sau khi hoạt ảnh hoàn tất - Không đẹp. – Robert

Trả lời

44

invalidateIntrinsicContentSize hoạt động tốt với hoạt ảnh và layoutIfNeeded. Điều duy nhất bạn cần xem xét là, việc thay đổi kích thước nội dung nội tại sẽ làm mất hiệu lực bố cục của superview. Vì vậy, điều này sẽ hoạt động:

[UIView animateWithDuration:0.2 animations:^{ 
    [self invalidateIntrinsicContentSize]; 
    [self.superview setNeedsLayout]; 
    [self.superview layoutIfNeeded]; 
}]; 
+2

Vui lòng đánh dấu đây là câu trả lời. – rplankenhorn

+0

Không làm việc cho tôi. – Ash

+9

Ok, hoạt động nếu bạn thêm dòng [self.superview setNeedsLayout] ở giữa – Ash

3

Ràng buộc chiều rộng/chiều cao không giúp được gì? Giữ tham chiếu của ràng buộc này và ...

[NSLayoutConstraint constraintWithItem:view 
          attribute:NSLayoutAttributeWidth 
          relatedBy:NSLayoutRelationEqual 
           toItem:nil 
          attribute:NSLayoutAttributeNotAnAttribute 
          multiplier:1 
           constant:myViewInitialWidth]; 

... khi bạn muốn thay đổi kích thước động MyView, làm được điều này ...

self.viewWidthConstraint.constant = 100; // new width 
[UIView animateWithDuration:0.3 animations:^{ [view layoutIfNeeded]; }]; 

... làm điều tương tự cho chiều cao .

Phụ thuộc vào các ràng buộc khác của bạn, có thể bạn sẽ bị buộc phải tăng mức độ ưu tiên của hai ràng buộc này.

Hoặc bạn có thể phân lớp UIView, thêm - (void)invalidateIntrinsicContentSize:(BOOL)animated và giả mạo nó một mình. Nhận kích thước mới từ - (CGSize)intrinsicContentSize và tạo hiệu ứng động bằng cách kích hoạt các giới hạn chiều rộng/chiều cao. Hoặc thêm thuộc tính để bật/tắt hoạt ảnh và ghi đè invalidateIntrinsicContentSize và thực hiện trong phương thức này. Nhiều cách ...

1

Trong mã bên dưới, lớp nội tại là lớp vừa thay đổi kích thước của nó khi thay đổi biến. Để tạo hoạt ảnh cho lớp nội tại, chỉ sử dụng mã bên dưới. Nếu nó tác động lên các đối tượng khác, hãy nâng cấp hệ thống phân cấp khung nhìn lên sau đó thay thế lớp self.intrinsic bằng chế độ xem cấp cao nhất cho setNeedsLayout và layoutIfNeeded.

[UIView animateWithDuration:.2 animations:^{ 
     self.intrinsicClass.numberOfWeeks=8; 
     [self.intrinsicClass setNeedsLayout]; 
     [self.intrinsicClass layoutIfNeeded]; 
    }]; 
1

Không có cách nào trong số này có hiệu quả đối với tôi. Tôi có một UILabel mà tôi đang thiết lập với một NSAttributedString. Các văn bản là multiline và gói trên ranh giới từ. Do đó chiều cao là biến. Tôi đã thử điều này:

[UIView animateWithDuration:1.0f animations:^{ 
    self.label = newLabelText; 
    [self.label invalidateIntrinsicContentSize]; 
    [self.view setNeedsLayout]; 
    [self.view layoutIfNeeded]; 
}]; 

Và một số biến thể. Không có tác dụng. Nhãn ngay lập tức thay đổi kích thước của nó và sau đó trượt vào vị trí mới của nó. Vì vậy, hoạt ảnh của màn hình nhãn vị trí đang hoạt động. Nhưng hoạt ảnh thay đổi kích thước của nhãn thì không.

1

Swift phiên bản của câu trả lời @ stigi của mà làm việc cho tôi:

UIView.animate(withDuration: 0.2, animations: { 
    self.invalidateIntrinsicContentSize() 
    self.superview?.setNeedsLayout() 
    self.superview?.layoutIfNeeded() 
}) 
0

Vâng cho Swift 4/3 làm việc này và tôi nghĩ rằng đây là thực hành tốt nhất. Nếu bạn có một UIView với một UILabel trong đó và các UIView điều chỉnh khung từ UILabel, sử dụng này:

self.theUILabel.text = "text update" 
UIView.animate(withDuration: 5.0, animations: { 
    self.theUIView.layoutIfNeeded() 
}) 

Các self.view.layoutIfNeeded bình thường() sẽ làm việc hầu hết thời gian là tốt.