【问题标题】:Animate UILabel width with auto layout使用自动布局为 UILabel 宽度设置动画
【发布时间】:2016-01-08 18:16:41
【问题描述】:

我正在尝试为 UILabel 的宽度设置动画。由于某种原因,动画不起作用,标签会立即改变它的大小。我使用自动布局。这是我为重现此问题而编写的示例项目中的代码。点击按钮会更改按钮和标签的尾随约束。

@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 子类不同,但我不明白为什么。

【问题讨论】:

  • 您的代码显示了篡改的证据:它设置了self.label3.text,但ViewController 没有label3 属性。当您不向我们展示您的真实代码时,很难为您提供帮助。无论如何,我怀疑你的标签在情节提要中的设置方式存在问题。

标签: ios objective-c uiviewanimation ios-autolayout


【解决方案1】:

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

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

[UIView animateWithDuration:0.5 animations:^{

    [self.view layoutIfNeeded];
}];

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

这对我每次都有效。希望这会有所帮助。

【讨论】:

  • 这也是我最初的反应,但我在自己的测试中发现了一个奇怪的行为:扩展标签时它工作得很好,但是当它再次缩小时它会跳跃......奇怪。
  • @Bogdan Balta:我明白你的意思,你建议了动画约束的标准方法,我知道。但是,这在我的代码中不是问题,因为按钮按预期动画。这个问题是特定于 UILabel 的。我将更改我的代码,因为它显然使人们感到困惑。请让我知道您是否可以让您的动画代码与 UILabel 一起使用。
  • @Bogdan Balta:您似乎是对的,这确实是调用 [self.view layoutIfNeeded];
【解决方案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;
        }];
    }
}

【讨论】:

  • 没有。我明白你的意思,你提出了动画约束的标准方法,我知道。但是,这在我的代码中不是问题,因为按钮按预期动画。这个问题是特定于 UILabel 的。我将更改我的代码,因为它显然使人们感到困惑。请让我知道您是否可以让您的动画代码与 UILabel 一起使用。
【解决方案3】:

要让这 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;
        }];
    }
}

【讨论】:

  • 没有。我明白你的意思,你提出了动画约束的标准方法,我知道。但是,这在我的代码中不是问题,因为按钮按预期动画。这个问题是特定于 UILabel 的。我将更改我的代码,因为它显然使人们感到困惑。请让我知道您是否可以让您的动画代码与 UILabel 一起使用。
  • 太棒了!我也刚刚连接了一个演示来验证。 :)
猜你喜欢
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-14
  • 2015-01-19
  • 2014-02-11
  • 1970-01-01
相关资源
最近更新 更多