使用自动布局为UILabel宽度设置动画

时间:2016-01-08 18:16:42

标签: ios objective-c uiviewanimation ios-autolayout

我试图为UILabel的宽度制作动画。由于某些原因,动画无法正常工作,并且标签会立即改变它的大小。我使用autolayout。这是我写的示例项目中的代码来重现这个。点击按钮可更改按钮和标签的尾随约束。

@interface ViewController ()

@property (assign, nonatomic) BOOL controlsResized;
@property (weak, nonatomic) IBOutlet UIButton *button;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *buttonTrailingConstraint;
@property (weak, nonatomic) IBOutlet MyLabel *label;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *labelTrailingConstraint;
- (IBAction)doTapButton:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.button setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.label setTranslatesAutoresizingMaskIntoConstraints:NO];
    self.label3.text = @"asdfasdfds sklfjfjls sdlkfj jjjjkfjkfdsjkdfsjklffsjkfdsjkl";
}    


- (IBAction)doTapButton:(id)sender
{
    if (!self.controlsResized)
    {
        [UIView animateWithDuration:0.5 animations:^{
            self.buttonTrailingConstraint.constant = 0;
            [self.button layoutIfNeeded];
            self.labelTrailingConstraint.constant = 0;
            [self.label layoutIfNeeded];

            self.controlsResized = YES;
        }];
    }
    else
    {
        [UIView animateWithDuration:0.5 animations:^{
            self.buttonTrailingConstraint.constant = 100;
            [self.button layoutIfNeeded];
            self.labelTrailingConstraint.constant = 100;
            [self.label layoutIfNeeded];

            self.controlsResized = NO;
        }];
    }
}

@implementation MyLabel

- (void)drawTextInRect:(CGRect)rect
{
    NSLog(@"drawTextInRect");
    [super drawTextInRect:rect];
}

@end

正如您在video上看到的那样,它适用于按钮,但不适用于标签。

我尝试从MyLabel类调查和子类化标签。看来,- (void)drawTextInRect:(CGRect)rect会在按钮点击时立即被调用,这是动画块中[self.label layoutIfNeeded];的原因。为什么会这样?我希望框架可以更改动画,因为它是在动画块中设置的。它的工作方式与UIButton一样。

为什么UILabel没有调整动画大小?有办法解决吗?

编辑: 我尝试了当前答案中提出的方法,但它们也不起作用。我认为动画代码在这里不是问题,因为它适用于我的示例中的按钮。问题似乎与UILabel具体有关。 UILabel似乎处理大小变化的动画与其他UIView子类不同,但我不明白为什么。

3 个答案:

答案 0 :(得分:3)

我会发表评论,但我没有必要的声誉。这就是我要做的事情:

self.buttonTrailingConstraint.constant = x;
self.labelTrailingConstraint.constant = x;

[UIView animateWithDuration:0.5 animations:^{

    [self.view layoutIfNeeded];
}];

当您更新约束时,您需要考虑到您正在修改的相应视图的约束不是唯一需要更新的约束,因此最好在父视图上进行布局方法调用。

每次都适合我。希望这会有所帮助。

答案 1 :(得分:2)

您必须在设置动画之前设置约束常量。

试试这个:

- (IBAction)doTapButton:(id)sender
{
    if (!self.controlsResized)
    {
        self.buttonTrailingConstraint.constant = 0;
        self.labelTrailingConstraint.constant = 0;

        [UIView animateWithDuration:0.5 animations:^{
            [self.view layoutIfNeeded];
        } completion:^(BOOL finished) {
            self.controlsResized = YES;
        }];
    }
    else
    {
        self.buttonTrailingConstraint.constant = 100;
        self.labelTrailingConstraint.constant = 100;

        [UIView animateWithDuration:0.5 animations:^{
            [self.view layoutIfNeeded];
        } completion:^(BOOL finished) {
            self.controlsResized = NO;
        }];
    }
}

答案 2 :(得分:2)

要使100%按预期工作,有几个部分:

  • 首先调用layoutIfNeeded
  • 在动画块之外设置约束常量
  • 在块内调用layoutIfNeeded

从工作实施中复制:

[self.view layoutIfNeeded];
self.topContainerConstraint.constant = constraintValue;
[UIView animateWithDuration:0.25 animations:^{
    [self.view layoutIfNeeded];
} completion:^(BOOL finished){ }];

我将您的功能更改为以下内容(显然未经测试):

- (IBAction)doTapButton:(id)sender
{
    if (!self.controlsResized)
    {
        [self.view layoutIfNeeded];
        self.labelTrailingConstraint.constant = 0;
        self.buttonTrailingConstraint.constant = 0;
        [UIView animateWithDuration:0.5 animations:^{
            [self.view layoutIfNeeded];
            self.controlsResized = YES;
        }];
    }
    else
    {
        [self.view layoutIfNeeded];
        self.labelTrailingConstraint.constant = 100;
        self.buttonTrailingConstraint.constant = 100;
        [UIView animateWithDuration:0.5 animations:^{
            [self.view layoutIfNeeded];
            self.controlsResized = NO;
        }];
    }
}