简体   繁体   English

为什么UILabel边界上的动画仅在增大尺寸时起作用?

[英]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. 我注意到当我在动画块中更改UILabel的边界时,它只有在我增加大小时才有效,当我减小大小时UILabel只是改变了它的大小但没有动画。 Replacing the UILabel with a plain UIView works as intended. 用普通的UIView替换UILabel按预期工作。

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. 注意:将UILabel的contentMode属性更改为UIViewContentModeScaleToFill可以解决此问题,但我仍然不明白为什么在增加大小而不更改contentMode属性时它可以正常工作。

#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

It's because UILabel sets its layer's contentsGravity to the direction text is being rendered, which happens to default to UIViewContentModeLeft (or @"left" ). 这是因为UILabel将其图层的contentsGravity设置为正在呈现文本的方向,这恰好默认为UIViewContentModeLeft (或@"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. 因为它看到@"left"应该有@"resize" ,它假定缩放动画应该从左边开始,但它也必须尊重你给它的约束(边界变化),所以你的标签似乎跳到它的最终大小,然后在屏幕中央的位置。

If you want to leave contentMode alone, use CATransform3D 's and scale the label's layer that way instead of a bounds change. 如果您想单独保留contentMode ,请使用CATransform3D并以此方式缩放标签的图层而不是边界更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM