Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate while resizing UIView

I saw some material on the web, but still can't quite get to where I want. I need to animate my view downwards, making it's height bigger.

Here is my code so far. What's happening here, is that instead of my view resizing, it's just changing it's location a bit up. If I change the proprty instead of "bounds.size" to be "transform.scale.y", it's a little better, only this time it expands the view both up and down, not just downwards.

Another thing I'm not of : are these keys just CALayer properties ? where I can find a list of these keys?

I would really appreciate help here. Thanks!

int x = self.btnHead.frame.origin.x;
int y = self.btnHead.frame.origin.y;
int height = self.btnHead.frame.size.height;
int width = self.btnHead.frame.size.width;


CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
[resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(width,height+50)]];
resizeAnimation.fillMode = kCAFillModeForwards;
resizeAnimation.removedOnCompletion = NO;

CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:resizeAnimation,nil];
animationGroup.removedOnCompletion = NO;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.removedOnCompletion=NO;
animationGroup.duration = 0.1;

[self.btnHead.layer addAnimation:animationGroup forKey:@"animations"];

Edit: posting my first code as requested - This will just change my view size, but won't animate , no matter the duration I enter.

    int x = self.btnHead.frame.origin.x;
    int y = self.btnHead.frame.origin.y;
    int height = self.btnHead.frame.size.height;
    int width = self.btnHead.frame.size.width;


    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:10];
    CGRect rect = CGRectMake(x,y,width ,height+BUTTON_HEIGH*2);

    self.btnHead.frame = rect;

    [UIView commitAnimations];
like image 383
Idan Avatar asked Jan 03 '11 16:01

Idan


2 Answers

Animating the frame property can be problematic, but it should work correctly as long as the transform is the identity (that is, you haven't changed it). I just tested the following code, and it worked as expected:

[UIView animateWithDuration:.1f animations:^{
  CGRect theFrame = myView.frame;
  theFrame.size.height += 50.f;
  myView.frame = theFrame;
}];

Again, this won't work as expected if you've changed the transform property at any time. For a more bulletproof version of this animation, you need to animate the bounds property like you tried to with Core Animation. You still don't need to drop into Core Animation, though.

The important thing to understand here is the relationship between the bounds and center properties. All affine transforms (translate, scale or rotate) need a reference point about which to perform the transform. In the case of a UIView that is the center point. CALayer lets you move the reference point around via the anchorPoint property, but we don't need to worry about that in this case.

The reason the view scales in both directions is that the scaling operation happens around the center. The easiest thing to to then, is to move the center y by half the height delta. Like this:

myView.contentMode = UIViewContentModeRedraw;
[UIView animateWithDuration:.4f animations:^{
  CGRect theBounds = myView.bounds;
  CGPoint theCenter = myView.center;
  theBounds.size.height += 50.f;
  theCenter.y += 25.f;
  myView.bounds = theBounds;
  myView.center = theCenter;
}];

The final consideration is forcing the view to redraw when the bounds changes. For performance reasons, the view will not redraw when you change its bounds. However, it does redraw when you change the frame property (yet another quirk of the frame property). To force a redraw on bounds change, you need to set the contentMode like I did in the first line of the previous snippet. You probably want to set it back after the animation finishes, but that's up to you. This is also the reason your Core Animation version only changes the location and not the size. You need this line in your code somewhere before you run the animation:

self.btnHead.layer.needsDisplayOnBoundsChange = YES;

I hope this all makes sense. The frame, bounds and center properties can be a little confusing at first.

like image 127
Nathan Eror Avatar answered Oct 19 '22 08:10

Nathan Eror


btnHead.clipsToBounds=YES

Solved the issue. Not sure exacly why.

like image 24
Idan Avatar answered Oct 19 '22 09:10

Idan