2016-01-08 112 views
2

我正在嘗試動畫UILabel的寬度。出於某種原因,動畫不起作用,標籤立即改變大小。我使用自動佈局。這裏是我寫的重現這個示例項目的代碼。點擊按鈕可更改按鈕和標籤的尾隨限制。使用自動佈局動畫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類調​​查和subclassed標籤。看起來,- (void)drawTextInRect:(CGRect)rect立即被按鈕按鈕調用,作爲[self.label layoutIfNeeded];在動畫塊中的原因。爲什麼這樣?我會期望幀被改變爲動畫,因爲它被設置在動畫塊內。它和UIButton的預期一樣。

爲什麼UILabel不調整動畫大小?有沒有辦法解決它?

編輯: 我嘗試了當前答案中提出的方法,但它們也不起作用。我認爲動畫代碼在這裏不是問題,因爲它適用於我的示例中的按鈕。這個問題似乎與UILabel具體有關。 UILabel似乎處理動畫的大小變化不同於其他UIView子類,但我不明白爲什麼。

+0

你的代碼顯示篡改的證據:它集'自我。 label3.text'但是'ViewController'沒有'label3'屬性。當你沒有向我們展示你真實的代碼時,很難幫助你。無論如何,我懷疑你的標籤在故事板中的設置方式存在問題。 –

回答

2

我會發表評論,但我沒有必要的聲譽。這裏是我會做什麼:

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

[UIView animateWithDuration:0.5 animations:^{ 

    [self.view layoutIfNeeded]; 
}]; 

當你更新你需要考慮到要修改相應的視圖的約束並不需要更新的唯一一個約束,所以佈局方法調用是更好的做在父視圖上。

這對我來說每次都有效。希望這可以幫助。

+3

這也是我最初的反應,但我在我自己的測試中遇到了一個奇怪的行爲:它在擴展標籤時非常完美,但是當它再次減少時,它會跳躍......奇怪。 – jcaron

+0

@Bogdan Balta:我明白你的意思,你提出了制定動畫約束的標準方法,並且我知道它。然而,這不是我的代碼中的問題,因爲按鈕動畫與預期的一樣。問題是UILabel特定的。我會改變我的代碼,因爲它顯然混淆了人。請讓我知道,如果你可以讓你的動畫代碼與UILabel一起工作。 – Anastasia

+0

@Bogdan Balta:你似乎是對的,這確實是調用[self.view layoutIfNeeded]的問題; – Anastasia

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; 
     }]; 
    } 
} 
+0

不,我明白你的意思,你提出了制定動畫約束的標準方法,我知道它。然而,這不是我的代碼中的問題,因爲按鈕動畫與預期的一樣。問題是UILabel特定的。我會改變我的代碼,因爲它顯然混淆了人。請讓我知道,如果你可以讓你的動畫代碼與UILabel一起工作。 – Anastasia

+0

它適用於我與一個UILabel .. – Pipiks

+0

嗯,你的代碼確實有效,謝謝。 – Anastasia

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; 
     }]; 
    } 
} 
+0

不,我明白你的意思,你提出了制定動畫約束的標準方法,並且我知道它。然而,這不是我的代碼中的問題,因爲按鈕動畫與預期的一樣。問題是UILabel特定的。我會改變我的代碼,因爲它顯然混淆了人。請讓我知道,如果你可以讓你的動畫代碼與UILabel一起工作。 – Anastasia

+0

是的,它的工作原理,謝謝。 – Anastasia

+0

太棒了!我只是連線演示來驗證。 :) – Ben