使用动画更改 CAShapeLayer 的位置
Changing position of CAShapeLayer using an animation
我有一个 UITextField
以我的 viewcontroller 为中心。我在文本字段下方使用 CAShapeLayer
,随着在文本字段中键入文本,宽度会增加。一旦用户按下回车键,隐藏在视图底部的 UITableView
就会向上滑动。我可以通过改变它们的约束来让 tableview 和 textfield 向上滑动。
func moveUp(){
searchBarTopConstraint.constant = 0
tableViewTopConstraint.constant = 0
UIView.animate(withDuration: 2.0) {
self.view.layoutSubviews()
}
}
但是,我不知道如何让 CAShapeLayer
与文本字段一起向上滑动。我尝试创建一个移动线条的函数并将其放入带有完成处理程序的 UIView 动画中,但线条会在动画之后或之前向上移动。
UIView.animate(withDuration: 2.00, delay: 0.0, options: [], animations: {
self.view.layoutSubviews()
self.moveLine()
}, completion: { (finished: Bool) in
// self.moveLine()
})
行的 y 位置由文本字段位置确定(这是 moveLine() 的简洁版本):
let y = searchField.frame.origin.y + searchField.frame.size.height + 6
linePath.move(to: CGPoint(x:x1, y:y))
linePath.addLine(to: CGPoint(x:x2, y:y))
有两个问题:
如果通过约束移动视图,则在动画块中调用 layoutIfNeeded()
,而不是 layoutSubviews()
正如 layoutSubviews()
documentation 所说:
You should not call this method directly. If you want to force a layout update, call the setNeedsLayout()
method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded()
method.
在你的情况下,将 layoutIfNeeded()
放在你的 animate
闭包中,而不是 layoutSubviews()
。
请注意,当您正确执行此操作时,这会移动您拥有 CAShapeLayer
的视图,而不是移动 CAShapeLayer
本身。因此,如果您有一个要移动的形状层,您可以将该形状层与一个带有约束的视图一起放置,然后使用上面的 layoutIfNeeded()
调用移动视图。
理论上,您实际上可以使用 CABasicAnimation
:
在视图中动画化 CAShapeLayer
的移动
let position = CGPoint(...) // the new origin of the CAShapeLayer within its view
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = shapeLayer.position // animate from current position ...
animation.toValue = position // ... to whereever the new position is
animation.duration = 2
shapeLayer.position = position // set the shape's final position to be the new position so when the animation is done, it's at its new "home"
shapeLayer.add(animation, forKey: nil) // animate from `fromValue` to `toValue`
就我个人而言,我认为在视图中移动形状图层有点令人困惑,我更喜欢将形状图层放在它自己的视图中,将该视图添加到具有相关约束的视图层次结构中,然后为其设置动画视图的约束。它使使用 Xcode 视图调试器调试视图更容易,恕我直言。
我有一个 UITextField
以我的 viewcontroller 为中心。我在文本字段下方使用 CAShapeLayer
,随着在文本字段中键入文本,宽度会增加。一旦用户按下回车键,隐藏在视图底部的 UITableView
就会向上滑动。我可以通过改变它们的约束来让 tableview 和 textfield 向上滑动。
func moveUp(){
searchBarTopConstraint.constant = 0
tableViewTopConstraint.constant = 0
UIView.animate(withDuration: 2.0) {
self.view.layoutSubviews()
}
}
但是,我不知道如何让 CAShapeLayer
与文本字段一起向上滑动。我尝试创建一个移动线条的函数并将其放入带有完成处理程序的 UIView 动画中,但线条会在动画之后或之前向上移动。
UIView.animate(withDuration: 2.00, delay: 0.0, options: [], animations: {
self.view.layoutSubviews()
self.moveLine()
}, completion: { (finished: Bool) in
// self.moveLine()
})
行的 y 位置由文本字段位置确定(这是 moveLine() 的简洁版本):
let y = searchField.frame.origin.y + searchField.frame.size.height + 6
linePath.move(to: CGPoint(x:x1, y:y))
linePath.addLine(to: CGPoint(x:x2, y:y))
有两个问题:
如果通过约束移动视图,则在动画块中调用
layoutIfNeeded()
,而不是layoutSubviews()
正如
layoutSubviews()
documentation 所说:You should not call this method directly. If you want to force a layout update, call the
setNeedsLayout()
method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call thelayoutIfNeeded()
method.在你的情况下,将
layoutIfNeeded()
放在你的animate
闭包中,而不是layoutSubviews()
。请注意,当您正确执行此操作时,这会移动您拥有
CAShapeLayer
的视图,而不是移动CAShapeLayer
本身。因此,如果您有一个要移动的形状层,您可以将该形状层与一个带有约束的视图一起放置,然后使用上面的layoutIfNeeded()
调用移动视图。理论上,您实际上可以使用
在视图中动画化CABasicAnimation
:CAShapeLayer
的移动let position = CGPoint(...) // the new origin of the CAShapeLayer within its view let animation = CABasicAnimation(keyPath: "position") animation.fromValue = shapeLayer.position // animate from current position ... animation.toValue = position // ... to whereever the new position is animation.duration = 2 shapeLayer.position = position // set the shape's final position to be the new position so when the animation is done, it's at its new "home" shapeLayer.add(animation, forKey: nil) // animate from `fromValue` to `toValue`
就我个人而言,我认为在视图中移动形状图层有点令人困惑,我更喜欢将形状图层放在它自己的视图中,将该视图添加到具有相关约束的视图层次结构中,然后为其设置动画视图的约束。它使使用 Xcode 视图调试器调试视图更容易,恕我直言。