55

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

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

我知道在半径更改时实施-(CGSize)intrinsicContentSize和调用invalidateIntrinsicContentSize会告诉约束要更新,但我不知道如何将更改设置为intrinsicContentSize.

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

这甚至可能吗,是否有解决方法/更好的方法?

4

6 回答 6

76

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

[UIView animateWithDuration:0.2 animations:^{
    [self invalidateIntrinsicContentSize];
    [self.superview setNeedsLayout];
    [self.superview layoutIfNeeded];
}];
于 2014-07-16T15:47:30.503 回答
9

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

UIView.animate(withDuration: 0.2, animations: {
    self.invalidateIntrinsicContentSize()
    self.superview?.setNeedsLayout()
    self.superview?.layoutIfNeeded()
})
于 2017-08-04T16:37:00.403 回答
3

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

[UIView animateWithDuration:.2 animations:^{
        self.intrinsicClass.numberOfWeeks=8;
        [self.intrinsicClass setNeedsLayout];
        [self.intrinsicClass layoutIfNeeded];
    }];
于 2014-06-23T13:04:18.433 回答
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并在此方法中执行。很多种方法 ...

于 2013-09-10T23:53:20.640 回答
0

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

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

以及多种变体。没有工作。标签会立即更改其大小,然后滑入新位置。所以屏幕上标签位置的动画正在工作。但是标签大小变化的动画不是。

于 2015-05-05T00:52:16.930 回答
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() 大部分时间也可以工作。

于 2017-08-18T00:40:26.460 回答