iOS - Animating text size change in UILabel or UIT

2020-06-04 03:51发布

问题:

In an application showing chunks of text, I'm having the font size increase when the device is turned to a landscape orientation. I don't like how it does the whole animation and then suddenly jumps to the new size, so I'd like to animate the size change over the course of the rotation.

I read somewhere that throwing this change in a UIView animation block doesn't work because the font property is not animatable, so what are my options for doing this?

For my specific implementation I'm not simply scaling the UILabel/UITextView as-is; The bounds of the box is increasing more (proportionally) than the font-size, so there will be re-flow in the text. That's fine by me.

Edit: I would be fine with simply scaling the UITextView.

Also, I was considering "animating" it manually: I have a method that lays out my views and adjusts for font size. If I knew when the rotation was about to start, and the duration of the animation, I could time it so it renders an intermediate font size or two in the middle of the animation. Any help with getting those would be appreciated.

回答1:

If I knew when the rotation was about to start, and the duration of the animation...

Funny you should mention that. Just before the animation starts, your view controller will receive a willAnimateRotationToInterfaceOrientation:duration: message that gives you the exact information you need.



回答2:

One option is to fade the old text out, change the font size, and fade it back in. The font property may not be animatable, but alpha is. Since alpha is a property of UIView, you can treat all your text-bearing views the same way: UILabel, UITextView, etc. It looks good, too.



回答3:

A way to proceed could be to:

  1. Create a CAKeyframeAnimation
  2. Define the scaling and rotation you want to achieve during that animation using a set of CATransform3D objects
  3. Add these transforms to your keyframed animation
  4. Send the addAnimation message to your label layer object: [[label layer] addAnimation];

Here would be a code sample assuming yourLabel is the UILabel you want to scale and rotate:

CAKeyframeAnimation *scale = [CAKeyframeAnimation animationWithKeyPath:@"transform"];

CATransform3D scaleUp = CATransform3DMakeScale(1.5, 1.5, 1); // Scale in x and y
CATransform3D rotationScaled = CATransform3DRotate (scaleUp, 90, 0, 0, 1); // Rotate the scaled font

[scale setValues:[NSArray arrayWithObjects:
[NSValue valueWithCATransform3D:CATransform3DIdentity],
[NSValue valueWithCATransform3D:rotationScaled],
nil]];

// set the duration
[scale setDuration: 1.0];

// animate your label layer
[[yourLabel layer] addAnimation:scale forKey:@"scaleText"];

This is typically how a text bouncing around would be animated for instance.

You could start this when the device starts rotating and retrieve the animation when it's done rotating so you can update your label with the proper scale/position.

You will need tuning to find the proper timing and rotation.



回答4:

Change the font size when didAnimateFirstHalfOfRotationToInterfaceOrientation: is called. That way the user won't see the change once the rotation completed. It would be pretty hard to see the font size change then, as the rotation is happening!