9

When increasing the height of label, everything is fine and smooth. When decreaseing, the label is instantly changing the size then repositioning with animation.

@interface
@property (nonatomic, retain) IBOutlet UILabel *explanationLabel;

@implementation
CGRect frmExpl = explanationLabel.frame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.75];

frmExpl.size.height -= height;
explanationLabel.frame = frmExpl;

[UIView commitAnimations];  

I've tried replacing UILabel with UIView and of course there is no such problem with UIView.

Is there any special way to animate UILabel size decrease?

Here is a minimal project demonstrating the issue described. Download

Pablo
  • 28,133
  • 34
  • 125
  • 215

3 Answers3

15

The issue is that the UILabel redraws itself as soon as its size changes. (It can't redraw every frame of the animation because text rendering happens on the CPU, not the GPU where UIView animations run.) You can keep it from redrawing by changing the label's contentMode property to, e.g., UIViewContentModeCenter.

davehayden
  • 3,484
  • 21
  • 28
2

Use a CGAffineTransform to do this.

[UIView animateWithDuration:1.0 animations:^{
    // Scale down 50%
    label.transform = CGAffineTransformScale(label.transform, 0.5, 0.5);
} completion:^(BOOL finished) {
    [UIView animateWithDuration:1.0 animations:^{
        // Scale up 50%
        label.transform = CGAffineTransformScale(label.transform, 2, 2);
    }];
}];
trapper
  • 11,716
  • 7
  • 38
  • 82
  • It worked for me but it affecting other animations like Fading in and fading out of the UIView. can you please tell me how to resolve this issue and why these animations are clashing. I have voted up your answer. – Developer Dec 16 '12 at 22:06
  • 2
    using affinetransformations on UILAbles does have some ugly sideeffects, like distorting the text on the label. not a useful solution. – katzenhut Nov 04 '13 at 13:26
2

I think what you are wanting to change is the bounds, rather than the frame. From the docs:

"The bounds rectangle determines the origin and scale in the view’s coordinate system within its frame rectangle and is measured in points. Setting this property changes the value of the frame property accordingly." - UIView Class; bounds property

Try something like:

- (void)animate:(id)sender
{
    ...
    CGRect newBounds = testLabel.bounds;
    newBounds.size.height += 50;
    testLabel.bounds = newBounds;
    ...
}
Matthew Leffler
  • 1,386
  • 1
  • 19
  • 36
  • Increasing bounds does change frame, but the frame remains same on the screen. Decreasing bounds works. But this is not solution, since I need both to increase and decrease. I suspect this is a bug in framework. – Pablo Jul 22 '10 at 00:06
  • 1
    True, it is probably a bug. Could you change your view hierarchy to have a UIView with the blue background and then a fixed-size UILabel that merely has its struts and springs set to float in the middle of the UIView. Given that the UIView animates correctly that might be a solution. – Matthew Leffler Jul 22 '10 at 20:59