I have a UIView subclass that draws a circle whose radius changes (with nice bouncy animations). The view is deciding the size of the circle.
I want this UIView subclass to change its frame size to match the animated changes to the circle radius, and I want these changes to modify any NSLayoutConstraints connected to the view (so that views that are constrained to the edge of the circle will move as the circle resizes).
I understand that implementing -(CGSize)intrinsicContentSize
and calling invalidateIntrinsicContentSize
when the radius changes will tell constraints to update, but I cant figure out how to animate the changes to intrinsicContentSize
.
Calling invalidateIntrinsicContentSize
from within a [UIView animateWith... block just instantly updates the layout.
Is this even possible, and is there a workaround/better approach?
invalidateIntrinsicContentSize
works well with animations and layoutIfNeeded
. The only thing you need to consider is, that changing the intrinsic content size invalidates the layout of the superview. So this should work:
[UIView animateWithDuration:0.2 animations:^{
[self invalidateIntrinsicContentSize];
[self.superview setNeedsLayout];
[self.superview layoutIfNeeded];
}];
Swift version of @stigi's answer which worked for me:
UIView.animate(withDuration: 0.2, animations: {
self.invalidateIntrinsicContentSize()
self.superview?.setNeedsLayout()
self.superview?.layoutIfNeeded()
})
Width / height constraint doesn't help? Keep reference of this constraint and ...
[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:myViewInitialWidth];
... when you do want to animate myView resize, do this ...
self.viewWidthConstraint.constant = 100; // new width
[UIView animateWithDuration:0.3 animations:^{ [view layoutIfNeeded]; }];
... do the same thing for the height.
Depends on your other constraints, maybe you will be forced to raise priority of these two constraints.
Or you can subclass UIView
, add - (void)invalidateIntrinsicContentSize:(BOOL)animated
and fake it by yourself. Get new size from - (CGSize)intrinsicContentSize
and animate it by animating width / height constraints. Or add property to enable / disable animations and override invalidateIntrinsicContentSize
and do it inside this method. Many ways ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With