Animate intrinsicContentSize更改

时间:2013-06-17 18:11:21

标签: cocoa-touch uiview nslayoutconstraint

我有一个UIView子类绘制一个半径变化的圆(具有漂亮的弹性动画)。视图决定了圆圈的大小。

我希望这个UIView子类更改其帧大小以匹配圆半径的动画更改,并且我希望这些更改可以修改连接到视图的任何NSLayoutConstraints(以便限制在圆的边缘的视图将随着圆圈调整大小而移动。)

我了解在半径更改时实施-(CGSize)intrinsicContentSize并调用invalidateIntrinsicContentSize将告知约束更新,但我无法弄清楚如何将更改设置为intrinsicContentSize的动画。

从[UIView animateWith ...块]中调用invalidateIntrinsicContentSize只是立即更新布局。

这是否可行,是否有解决方法/更好的方法?

6 个答案:

答案 0 :(得分:56)

invalidateIntrinsicContentSize适用于动画和layoutIfNeeded。您唯一需要考虑的是,更改内在内容大小会使superview的布局无效。所以这应该有效:

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

答案 1 :(得分: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]; }];

......为身高做同样的事情。

取决于您的其他约束,也许您将被迫提高这两个约束的优先级。

或者您可以继承UIView,添加- (void)invalidateIntrinsicContentSize:(BOOL)animated并自行伪造。从- (CGSize)intrinsicContentSize获取新大小,并通过设置宽度/高度限制动画来设置动画。或者添加属性以启用/禁用动画并覆盖invalidateIntrinsicContentSize并在此方法中执行此操作。很多方式......

答案 2 :(得分:2)

在下面的代码中,内部类是在更改变量时刚改变它的大小的类。要为内在类设置动画,只需使用下面的代码。如果它影响视图层次结构中更高的其他对象,则将self.intrinsic类替换为setNeedsLayout和layoutIfNeeded的顶级视图。

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

答案 3 :(得分:2)

快速版本的@ stigi的答案对我有用:

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

答案 4 :(得分:1)

这些都不适用于我。我有一个UILabel,我用NSAttributedString设置。文本是多行的并且包装在单词边界上。因此高度是可变的。我试过这个:

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

还有很多变化。没有工作。标签立即改变它的大小,然后滑入它的新位置。因此标签位置屏幕上的动画正在运行。但是标签尺寸变化的动画不是。

答案 5 :(得分:0)

对于Swift 4/3来说,这是有效的,我认为这是最好的做法。如果你有一个带有UILabel的UIView并且UIView从UILabel调整帧,请使用:

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

正常的self.view.layoutIfNeeded()也可以在大部分时间内工作。