2013-06-17 33 views
36

私は半径が変化する円を描画するUIViewサブクラスを持っています(素敵なバウンシーアニメーションで)。ビューは円のサイズを決定しています。アニメーションintrinsicContentSizeの変更

このUIViewサブクラスの円の半径に対するアニメーション化された変更に合わせてフレームサイズを変更し、ビューに接続されているNSLayoutConstraintsを変更するようにしたい(サークルのエッジに制限されたビューサークルのサイズが変更されると移動します)。

半径を変更したときにを呼び出すとを呼び出すと、制約が更新されることがわかりますが、変更をintrinsicContentSizeにアニメートする方法はわかりません。

[UIView animateWith ...ブロック内からinvalidateIntrinsicContentSizeを呼び出すと、ただちにレイアウトが更新されます。

これは可能なのでしょうか?回避策とより良いアプローチがありますか?

+0

これはできないと感じています。 'intrinsicContentSize'のフォントサイズの関数である' UILabel'の例を見てください。しかし、フォントの変更をアニメートする良い方法はありません。ラベルの回避策は、レイヤのトランスフォームの変更を(CAAnimationを使用して)アニメートし、アニメーションが完了した後にフォントを変更することです。 – Robert

答えて

44

invalidateIntrinsicContentSizeは、アニメーションやlayoutIfNeededでうまく動作します。あなたが考慮する必要があるのは、本質的なコンテンツサイズを変更するとスーパービューのレイアウトが無効になることだけです。だからこれはうまくいくはずです:

[UIView animateWithDuration:0.2 animations:^{ 
    [self invalidateIntrinsicContentSize]; 
    [self.superview setNeedsLayout]; 
    [self.superview layoutIfNeeded]; 
}]; 
+2

答えとしてマークしてください。 – rplankenhorn

+0

私のために働いていません。 – Ash

+9

@ Ashのフィードバックで更新された – Ash

3

幅/高さの制約は役に立ちませんか?この制約の参照を保持して...

[NSLayoutConstraint constraintWithItem:view 
          attribute:NSLayoutAttributeWidth 
          relatedBy:NSLayoutRelationEqual 
           toItem:nil 
          attribute:NSLayoutAttributeNotAnAttribute 
          multiplier:1 
           constant:myViewInitialWidth]; 

...あなたはMYVIEWサイズ変更アニメーション化したいとき、これを行う...

self.viewWidthConstraint.constant = 100; // new width 
[UIView animateWithDuration:0.3 animations:^{ [view layoutIfNeeded]; }]; 

...高さのために同じことを行います。

他の制約によっては、これらの2つの制約の優先順位を高く設定することを余儀なくされるかもしれません。

UIViewをサブクラス化し、- (void)invalidateIntrinsicContentSize:(BOOL)animatedを追加して自分で偽造することができます。 - (CGSize)intrinsicContentSizeから新しいサイズを取得し、幅/高さの制約をアニメーション化してアニメーション化します。または、プロパティを追加してアニメーションを有効/無効にし、invalidateIntrinsicContentSizeを上書きしてこのメ​​ソッド内で実行します。多くの方法...

1

以下のコードでは、組み込みクラスは変数の変更時にサイズを変更したばかりのクラスです。イントリンシッククラスをアニメートするには、以下のコードを使用します。ビュー階層の上位の他のオブジェクトに影響を与える場合は、self.intrinsicクラスをsetNeedsLayoutおよびlayoutIfNeededの最上位ビューに置き換えます。

[UIView animateWithDuration:.2 animations:^{ 
     self.intrinsicClass.numberOfWeeks=8; 
     [self.intrinsicClass setNeedsLayout]; 
     [self.intrinsicClass layoutIfNeeded]; 
    }]; 
1

これは私のために働いていません。私はNSAttributedStringで設定しているUILabelを持っています。テキストは複数行であり、ワード境界に折り返します。したがって、高さは可変である。私はこれを試しました:

[UIView animateWithDuration:1.0f animations:^{ 
    self.label = newLabelText; 
    [self.label invalidateIntrinsicContentSize]; 
    [self.view setNeedsLayout]; 
    [self.view layoutIfNeeded]; 
}]; 

と多くのバリエーション。なし。ラベルはすぐにサイズを変更し、新しい位置にスライドします。したがって、画面上のラベル位置のアニメーションが機能しています。しかし、ラベルのサイズ変更のアニメ化はそうではありません。

1

スウィフト私のために働いたの@ stigiの答えのバージョン:

UIView.animate(withDuration: 0.2, animations: { 
    self.invalidateIntrinsicContentSize() 
    self.superview?.setNeedsLayout() 
    self.superview?.layoutIfNeeded() 
}) 
0

まあスウィフト4/3のため、この作品、私はこれが最善の方法だと思います。あなたはそれでUILabelでのUIViewを持っており、UIViewのはUILabelからフレームを適応した場合は、これを使用する:

self.theUILabel.text = "text update" 
UIView.animate(withDuration: 5.0, animations: { 
    self.theUIView.layoutIfNeeded() 
}) 

通常self.view.layoutIfNeededを()だけでなく、ほとんどの時間を動作します。

関連する問題