我在viewcontroller中居中UITextField
。我在文本字段下面使用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位置由textfields位置决定(这是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))
答案 0 :(得分:1)
有两个问题:
如果通过约束移动视图,则在动画块中调用layoutIfNeeded()
,而不是layoutSubviews()
正如layoutSubviews()
documentation所说:
您不应该直接调用此方法。如果要强制进行布局更新,请在下次绘图更新之前调用
setNeedsLayout()
方法。如果您想立即更新视图的布局,请调用layoutIfNeeded()
方法。
在您的情况下,请将layoutIfNeeded()
放入animate
封闭内,而不是layoutSubviews()
。
请注意,当您正确执行此操作时,会移动您拥有CAShapeLayer
的视图,而不会移动CAShapeLayer
本身。因此,如果您有要移动的形状图层,则可以将该形状图层放在带有约束的视图中,然后使用上述layoutIfNeeded()
调用移动视图。
从理论上讲,您实际上可以使用CAShapeLayer
为视图中CABasicAnimation
的移动设置动画:
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视图调试器调试视图变得更加容易,恕我直言。