我有一个UIView子类绘制一个半径变化的圆(具有漂亮的弹性动画)。视图决定了圆圈的大小。
我希望这个UIView子类更改其帧大小以匹配圆半径的动画更改,并且我希望这些更改可以修改连接到视图的任何NSLayoutConstraints(以便限制在圆的边缘的视图将随着圆圈调整大小而移动。)
我了解在半径更改时实施-(CGSize)intrinsicContentSize
并调用invalidateIntrinsicContentSize
将告知约束更新,但我无法弄清楚如何将更改设置为intrinsicContentSize
的动画。
从[UIView animateWith ...块]中调用invalidateIntrinsicContentSize
只是立即更新布局。
这是否可行,是否有解决方法/更好的方法?
答案 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()也可以在大部分时间内工作。