AutoLayout 约束动画从错误的点缩放
Posted
技术标签:
【中文标题】AutoLayout 约束动画从错误的点缩放【英文标题】:AutoLayout constraint animation scales from wrong point 【发布时间】:2018-08-22 14:29:39 【问题描述】:我正在尝试使用自动布局约束实现动画,并与 UIStackViews 一起工作。我遇到了一个动画。
我有一个嵌套在 UIView(橙色)中的 UIImageView(绿色),它又由 UIStackView 处理。当只有这些元素可见时,视图应该缩小。我正在尝试更改以下约束:
通常宽度和高度为 64,前导/尾随/顶部/底部约束为 10,我使用以下方法将它们分别更改为 46 和 7:
private func setImageShrunk()
imageWidth.constant = 46
imageHeight.constant = 46
imageTopMargin.constant = 7
imageBottomMargin.constant = 7
imageRightMargin.constant = 7
imageLeftMargin.constant = 7
这个函数被另一个函数调用:
func shrinkImage(animated: Bool)
if(animated)
UIView.animate(withDuration: 1)
self.setImageShrunk()
self.layoutIfNeeded()
else
setImageShrunk()
在没有动画的情况下缩小图像会返回预期的结果,当然是突然的。但是,尝试对其进行动画处理,我得到以下结果:
我希望视图向左上角缩小,而不是从中心缩小。它不应该“先移动,后扩展”。有谁知道如何在 ios 11 中使用 AutoLayout 来实现这一点?
【问题讨论】:
如果您使用 0 而不是 7 作为顶部和左侧边距会发生什么? 抱歉,我认为页边距适用于橙色视图及其超级视图。您可以将橙色视图的顶部和左侧的约束设置为其超级视图,并在 shrinkImage 方法中将它们设置为 0 @AliMoazenzadeh 顶部和左侧的约束已经设置为 0,这就是为什么发生这种情况让我如此困惑的原因 您可以尝试将顶部和左侧边距限制优先级设置为低于 1000 的值吗?以 990 为例 @AliMoazenzadeh 我已经尝试过使用优先级,结果是even weirder... 【参考方案1】:所以我弄清楚了尝试制作一个小项目来重新创建错误时发生了什么。
在第二个项目中,设置是相同的,但动画效果符合我的预期。经过一番思考,我意识到在这个新项目中,我将动画从 UIViewController
包含 UIStackView
调用。
在最初的问题中,我没有提到 我正在从扩展 UIStackView
的类中调用动画,因此视图本身会被动画化。即使它从外部引用了约束,视图也不知道它的环境和嵌入视图。这就是为什么它只是跳跃然后缩放。
我通过将要完成的动画传输到包含UIStackView
的UIViewController
来解决此问题。
【讨论】:
谢谢,在我的情况下,我只需要在父视图上调用layoutIfNeeded()
,而不是动画视图本身【参考方案2】:
如果您设置了 width 和 height ,则不需要 right 和 bottom 约束,因为当您将 height 从 64 更改为 46 时,底部距离应为 28 ( 10 + 18 ),并且由于您将其设置为 7 ,那么就有冲突了,对的也一样,要么删除它们,要么降低它们的优先级
顺便说一句,所有这些只有在橙色视图有其他宽度和高度约束时才有效
【讨论】:
【参考方案3】:你设置了 UIView 的锚点了吗?它现在在中心点收缩,而不是左上角。您还应该创建一个自定义动画来定义两个动画并将它们链接在一起。您可以在网上找到很多解决方案,但这里是一个示例。是针对 sprite kit 的,但是思路是一样的。
#if os(iOS)
let transform:SKAction = SKAction.move(to: CGPoint(x: -40, y: -45), duration: 0.3)
let rotateAction:SKAction = SKAction.rotate(toAngle: degree(-20), duration: 0.3)
#else
let transform:SKAction = SKAction.move(to: CGPoint(x: -40, y: 60), duration: 0.3)
let rotateAction:SKAction = SKAction.rotate(toAngle: degree(-20), duration: 0.3)
#endif
let endAction:SKAction = SKAction.perform(#selector(GameScene.animateToTableEnded), onTarget: self)
let combineAction:SKAction = SKAction.sequence([SKAction.group([transform, rotateAction]), endAction])
实际上这里的分组创造了魔力。
这是来自 Apple 文档的核心动画解决方案。
let fadeOut = CABasicAnimation(keyPath: "opacity")
fadeOut.fromValue = 1
fadeOut.toValue = 0
fadeOut.duration = 1
let expandScale = CABasicAnimation()
expandScale.keyPath = "transform"
expandScale.valueFunction = CAValueFunction(name: kCAValueFunctionScale)
expandScale.fromValue = [1, 1, 1]
expandScale.toValue = [3, 3, 3]
let fadeAndScale = CAAnimationGroup()
fadeAndScale.animations = [fadeOut, expandScale]
fadeAndScale.duration = 1
【讨论】:
以上是关于AutoLayout 约束动画从错误的点缩放的主要内容,如果未能解决你的问题,请参考以下文章
同时使用不同的动画曲线为 AutoLayout 约束设置动画