10

I've been trying to figure out a decent way to smoothly animate a frame size change on a UILabel, without a weird starting jump redraw. What happens by default is that when I do something like this:

// Assume myLabel frame starts as (0, 0, 100, 200) 
[UIView beginAnimations:@"myAnim" context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:1.0];
myLabel.frame = CGRectMake(0.0, 0.0, 50, 100);
[UIView commitAnimations];  

I get a smooth animation with the label, however the way that it does it is that it takes the redrawn image layer for the destination size of the label and streches the content to fit the current then animates to the destination rect. This ends up with a very bizarre jump in the text display. Here are two images showing the pre-animation look, and then just after the animation starts:

Pre-Animation

Post-Animation

I have tried to use just the layer to animate this, but I still get the same issues.

So the question is, how can I avoid this?

Thanks for any help,
Scott

Community
  • 1
  • 1
Scott Little
  • 1,929
  • 15
  • 16
  • 1
    It's an old question but I'm fighting with exactly the same problem. Somehow it is illogical. As I understand the animation methods you should be able to animate most of the properties on a UIView class. But why does the frame property of a UILabel behave differently when animating than a normal UIView subclass. It looks like the UILabel class is ignoring the animation for the size and only animates the location change. Which creates a rather strange looking animation. I would appreciate if somebody could help me with this. – Chris Nov 12 '10 at 07:42

5 Answers5

40

Hooray for answering a two-year dead question, but I found the answer. Either in Interface Builder or in code, change the contentMode property of the label. Yours seems to be set on scaleToFill; try left or right.

cliclcly
  • 428
  • 5
  • 10
  • 1
    If I could, I would up this answer with 100! (It still jumps sometimes, but it's ok) – Ariel Nov 29 '11 at 08:22
  • TopLeft/Right or BottomLeft/Right could be the correct contentMode you want depending on the exact animation you need. – CedricSoubrie Mar 30 '14 at 11:05
  • 1
    it saved my life :) – Dmitry Jan 18 '17 at 20:02
  • 2
    this answer 100% works, but for a little more clarity, if my `.textAlignment` was `.center` as in: `myLabel.textAlignment = .center`, then set the `.contentMode` to: `myLabel.contentMode = .center` – Lance Samaria May 18 '21 at 07:26
7

To expand on @cliclcly's answer: From the Overview of UILabel's documentation:

The default content mode of the UILabel class is UIViewContentModeRedraw. This mode causes the view to redraw its contents every time its bounding rectangle changes. You can change this mode by modifying the inherited contentMode property of the class.

From the documentation of the contentMode property of UIView:

The default value of this property is UIViewContentModeScaleToFill.

UILabels behave differently than other UIViews by default because their contentMode property is different by default.

titaniumdecoy
  • 18,900
  • 17
  • 96
  • 133
7

I found that UIlabel frame animations are weird - their size is set immediatly to the end size and the text is rendered for that size. After that only the position change is animated, which means that if the destination size is (0,0) then the label disappears immediately. To circumvent this limitation I have placed the label inside a view of the same size that clips subviews, disabled autoresizing for the label, and I'm animating the label's superview instead of the label itself. The end result is that the label frame is fully animated throughout but the contained text isn't re-rendered with, say, a different font size nor does text truncation change. It's still not perfect, but it's fit for my purpose.

Initial frame:

initial frame

During animation:

During animation

Animation ended:

Animation ended

user3099609
  • 2,318
  • 18
  • 20
  • I can't believe believe I never knew this about UILabels. But you helped me solve a problem that had me totally stumped - thanks! – Echelon Mar 08 '16 at 17:23
0

Animating the frame doesn't animate changing the font size. If I understand what you behavior you are seeing, I think you have the label's adjustsFontSizeToFitWidth set to 'True' so you're seeing the frame animate to size followed by the instantaneous readjustment of the font size.

You might try to scale the label's transform so that the frame and font scale simultaneously.

TechZen
  • 64,370
  • 15
  • 118
  • 145
  • 1
    Actually no this isn't the case. The adjustFontSizeToFitWidth isn't set here and I'm actually *not* trying to change the font size, just the frame - which is in yellow. However what happens is that the dest frame (in this case) "fits" the text, so it first redraws that layer stretches it to fit the original frame, then reduces it. That's why it looks weird like this. – Scott Little Nov 18 '09 at 12:48
  • not sure then. Its an interesting problem. I'll see if I can't reproduce it later today. I'm curious myself. – TechZen Nov 18 '09 at 16:07
-3

Just turn off auto-layout for your label.

In Xcode, click on the label and then in the properties pane, un-check the auto-layout option

farid98
  • 131
  • 1
  • 6