Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate intrinsicContentSize changes

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?

like image 316
Loz Avatar asked Jun 17 '13 18:06

Loz


3 Answers

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];
}];
like image 145
stigi Avatar answered Nov 05 '22 12:11

stigi


Swift version of @stigi's answer which worked for me:

UIView.animate(withDuration: 0.2, animations: {
    self.invalidateIntrinsicContentSize()
    self.superview?.setNeedsLayout()
    self.superview?.layoutIfNeeded()
})
like image 41
nathangitter Avatar answered Nov 05 '22 14:11

nathangitter


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 ...

like image 3
zrzka Avatar answered Nov 05 '22 13:11

zrzka