Cocoa touch 设置intrinsicContentSize更改的动画

Cocoa touch 设置intrinsicContentSize更改的动画,cocoa-touch,uiview,nslayoutconstraint,Cocoa Touch,Uiview,Nslayoutconstraint,我有一个UIView子类,它绘制一个半径变化的圆(带有漂亮的反弹动画)。视图决定了圆的大小 我希望此UIView子类更改其帧大小以匹配对圆半径的动画更改,并希望这些更改修改连接到视图的任何NSLayoutConstraints(以便约束到圆边缘的视图将随着圆的大小调整而移动) 我知道在半径更改时实现-(CGSize)intrinsicContentSize并调用invalidateIntrinsicContentSize将通知约束进行更新,但我不知道如何设置对intrinsicContentSi

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

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

我知道在半径更改时实现
-(CGSize)intrinsicContentSize
并调用
invalidateIntrinsicContentSize
将通知约束进行更新,但我不知道如何设置对
intrinsicContentSize
的更改的动画

从[UIView animateWith…块中调用
invalidateIntrinsicContentSize
,即可立即更新布局


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

宽度/高度约束没有帮助?请保留此约束的引用并

[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
,并在该方法内执行此操作。许多方法…

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

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

<代码> SuffiTrimePixCieldCistNosis与动画和<代码> LayuthI需用很好地结合。唯一需要考虑的是,改变内部内容大小使超级视图的布局无效。因此,这应该起作用:

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

所有这些对我都不起作用。我有一个UILabel,我正在使用NSAttributed字符串设置它。文本是多行的,并在单词边界上换行。因此高度是可变的。我尝试过以下方法:

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

还有很多变化。都不起作用。标签会立即改变它的大小,然后滑动到它的新位置。因此,屏幕上标签位置的动画可以工作。但是标签大小变化的动画不起作用。

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

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

对于Swift 4/3来说,这很有效,我认为这是最好的做法。如果您有一个带有UILabel的UIView,并且UIView根据UILabel调整框架,请使用以下方法:

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

普通的self.view.layoutifneed()文件大部分时间都可以。我感觉这是不可能的。以
UILabel
为例,它的
intrinsicContentSize
是字体大小的函数。但是,没有很好的方法来设置字体更改的动画。标签的解决方法是设置其层的变换更改的动画(使用
CAAnimation
)然后在动画完成后更改字体-不太好。如果添加行[self.superview setNeedsLayout],则可以正常工作在中间,更新了@Ash的反馈。这对于
UIView
s和
intrinsicContentSize
inside
UIStackView
。为了使堆栈视图在调整大小时具有动画效果,必须在堆栈的父级上调用
layoutIfNeeded
,而不是在堆栈本身上。我刚刚被它咬了一口!这可能是评论,因为它不提供答案。