Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
401 views
in Technique[技术] by (71.8m points)

ios - Why are animations on bounds of an UILabel only working when increasing the size?

I noticed that when i change the bounds of an UILabel in an animation block it only works if i increase the size, when i decrease the size the UILabel just changes his size but doesn't animate. Replacing the UILabel with a plain UIView works as intended.

Note: Changing the contentMode property of the UILabel to UIViewContentModeScaleToFill fixes this issue, but i still don't understand why it works when increasing the size without changing the contentMode property.

#import "FooView.h"

@interface FooView ()
@property (strong, nonatomic) UILabel   *label;
@property (assign, nonatomic) BOOL       resized;
@end

@implementation FooView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor lightGrayColor];

        self.label = [[UILabel alloc] initWithFrame:(CGRect){0, 0, frame.size}];
        self.label.backgroundColor = [UIColor greenColor];
        [self addSubview:self.label];
        _resized = false;

        UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(changeSize)];
        tapRecognizer.numberOfTapsRequired = 1;
        [self addGestureRecognizer:tapRecognizer];
    }
    return self;
}

- (void)changeSize {
    [UIView animateWithDuration:0.8
                          delay:0.0
                        options:UIViewAnimationOptionCurveEaseIn
                     animations:^{
                         CGRect bounds = self.label.bounds;
                         if (self.resized) {
                             bounds.size.height *= 2;
                             bounds.size.width  *= 2;
                         } else {
                             bounds.size.width  /= 2;
                             bounds.size.height /= 2;
                         }
                         self.label.bounds = bounds;
                     }
                     completion:^(BOOL finished) {
                         self.resized = !self.resized;
                     }];
}

@end
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's because UILabel sets its layer's contentsGravity to the direction text is being rendered, which happens to default to UIViewContentModeLeft (or @"left"). Thus, when the layer is told to animate, it first takes a glance at its contents gravity and bases subsequent animations on that. Because it sees @"left" where there should be @"resize", it assumes that the scaling animation should begin from the left, but it also has to respect the constraints you've given it (the bounds changes), so your label appears to jump into its final size then settle where it should in the center of the screen.

If you want to leave contentMode alone, use CATransform3D's and scale the label's layer that way instead of a bounds change.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...