UIView 在使用约束缩放后动画到错误的位置
UIView animating to wrong position after being scaled while using constraints
所以我正在尝试制作一个 UILabel
的动画以匹配另一个 UILabel
大小和位置。起初我只使用这样的约束来处理位置部分的动画:
private lazy var constraintsForStateA: [NSLayoutConstraint] = [
firstLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
firstLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor)
]
private lazy var constraintsForStateB: [NSLayoutConstraint] = [
firstLabel.leadingAnchor.constraint(equalTo: secondLabel.leadingAnchor),
firstLabel.topAnchor.constraint(equalTo: secondLabel.topAnchor)
]
所以我基本上有两个具有上述约束的数组(constraintsForStateA
和 constraintsForStateB
),当我需要为我的 firstLabel
的位置设置动画时,我只需要执行如下操作:
// From state A to state B
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut) {
NSLayoutConstraint.deactivate(self._constraintsUnselected)
NSLayoutConstraint.activate(self._constraintsSelected)
self.layoutIfNeeded()
} completion: { _ in
self.firstLabel.alpha = 0
self.secondLabel.alpha = 1
}
}
到目前为止,这完全符合我的预期,但是大小部分给我带来了一些麻烦,因为我不能对文本大小应用相同的策略我正在使用这样的转换:
let scaleX = secondLabel.bounds.width / firstLabel.bounds.width
let scaleY = secondLabel.bounds.height / firstLabel.bounds.height
然后在上面相同的 .animate 方法中从状态 A 到状态 B 我这样做:
firstLabel.transform = CGAffineTransform(scaleX: scaleX, y: scaleY)
从B状态到A状态:
firstLabel.transform = .identity
按我的意愿工作,但我面临的问题是该位置不再位于预期位置。我认为发生这种情况是因为考虑到标签中心的 anchorPoint
,正在发生转换。我尝试过将 anchorPoint
更改为 (0,0)
,但它也不起作用。我已经为此浪费了 2 天时间,欢迎任何帮助或指导!
当你做动画的时候,如果你忘记约束而只处理帧会简单得多:
NSLayoutConstraint.deactivate(self.constraintsForStateA)
firstLabel.translatesAutoresizingMaskIntoConstraints = true
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut) {
firstLabel.frame = secondLabel.frame
}
然后从状态B转换到A:
firstLabel.translatesAutoresizingMaskIntoConstraints = false
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut) {
NSLayoutConstraint.activate(self.constraintsForStateA)
self.layoutIfNeeded()
}
所以我正在尝试制作一个 UILabel
的动画以匹配另一个 UILabel
大小和位置。起初我只使用这样的约束来处理位置部分的动画:
private lazy var constraintsForStateA: [NSLayoutConstraint] = [
firstLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
firstLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor)
]
private lazy var constraintsForStateB: [NSLayoutConstraint] = [
firstLabel.leadingAnchor.constraint(equalTo: secondLabel.leadingAnchor),
firstLabel.topAnchor.constraint(equalTo: secondLabel.topAnchor)
]
所以我基本上有两个具有上述约束的数组(constraintsForStateA
和 constraintsForStateB
),当我需要为我的 firstLabel
的位置设置动画时,我只需要执行如下操作:
// From state A to state B
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut) {
NSLayoutConstraint.deactivate(self._constraintsUnselected)
NSLayoutConstraint.activate(self._constraintsSelected)
self.layoutIfNeeded()
} completion: { _ in
self.firstLabel.alpha = 0
self.secondLabel.alpha = 1
}
}
到目前为止,这完全符合我的预期,但是大小部分给我带来了一些麻烦,因为我不能对文本大小应用相同的策略我正在使用这样的转换:
let scaleX = secondLabel.bounds.width / firstLabel.bounds.width
let scaleY = secondLabel.bounds.height / firstLabel.bounds.height
然后在上面相同的 .animate 方法中从状态 A 到状态 B 我这样做:
firstLabel.transform = CGAffineTransform(scaleX: scaleX, y: scaleY)
从B状态到A状态:
firstLabel.transform = .identity
按我的意愿工作,但我面临的问题是该位置不再位于预期位置。我认为发生这种情况是因为考虑到标签中心的 anchorPoint
,正在发生转换。我尝试过将 anchorPoint
更改为 (0,0)
,但它也不起作用。我已经为此浪费了 2 天时间,欢迎任何帮助或指导!
当你做动画的时候,如果你忘记约束而只处理帧会简单得多:
NSLayoutConstraint.deactivate(self.constraintsForStateA)
firstLabel.translatesAutoresizingMaskIntoConstraints = true
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut) {
firstLabel.frame = secondLabel.frame
}
然后从状态B转换到A:
firstLabel.translatesAutoresizingMaskIntoConstraints = false
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut) {
NSLayoutConstraint.activate(self.constraintsForStateA)
self.layoutIfNeeded()
}