I have two views between which is located resizable line (view with CAShapeLayer). The problem that I'm facing with is that despite the animation on layer, it is appearing faster than views are changing. I know that animation of layer is completely different, but can't understand where is my fault. Please tell me if I made something wrong.
Here is the code of my layer's animation (used "strokeStart" as well, but it didn't worked):
override func layoutSubviews() {
super.layoutSubviews()
let centerX = bounds.size.width / 2
let path = CGMutablePath()
path.addLines(between: [CGPoint(x: centerX, y: 0), CGPoint(x: centerX, y: frame.height)])
dashedLayer.path = path
dashedLayer.frame = bounds
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = height
animation.toValue = bounds.size.height
height = bounds.size.height
animation.duration = 0.3
dashedLayer.add(animation, forKey: nil)
}
Code of views' animation (because of modifying views, I animate layoutIfNeeded):
UIView.animate(withDuration: 0.3, animations: {
self.view.layoutIfNeeded()
...
I think one easy way to deal with this is to animate the constraint constant like this:
@IBOutlet weak var heightConstraint: NSLayoutConstraint!
UIView.animate(withDuration: 3, animations: {
self. heightConstaint.constant = 300 // This constant is the height of top big view.
self.view.layoutIfNeeded()}
There is another view where the CAShapeLayer lies in. I call it line View
. Its height should be constrained as same as the height of the top big view
.
In the line view
, you can add animations. This should be similar to your implementation.
override func didMoveToSuperview() {
super.didMoveToSuperview()
dashedLayer.backgroundColor = UIColor.clear.cgColor
layer.addSublayer(dashedLayer)
height = bounds.size.height
}
override func layoutSubviews() {
super.layoutSubviews()
let centerX = bounds.size.width / 2
let path = CGMutablePath()
path.addLines(between: [CGPoint(x: centerX, y: 0), CGPoint(x: centerX, y: frame.height)])
dashedLayer.path = path
dashedLayer.lineWidth = 3.0
dashedLayer.strokeColor = UIColor.blue.cgColor
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = height / bounds.size.height
animation.toValue = 1.0
animation.timingFunction = CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeInEaseOut)
height = bounds.size.height
animation.duration = 3.0
dashedLayer.add(animation, forKey: nil)
}
It's expanding here. You may adapt the code to contract by yourself.
The following is with the reversing animation.
override func didMoveToSuperview() {
super.didMoveToSuperview()
dashedLayer.backgroundColor = UIColor.clear.cgColor
layer.addSublayer(dashedLayer)
height = bounds.size.height
clipsToBounds = true
}
override func layoutSubviews() {
super.layoutSubviews()
let centerX = bounds.size.width / 2
let path = CGMutablePath()
path.addLines(between: [CGPoint(x: centerX, y: 0), CGPoint(x: centerX, y: max(height , bounds.size.height) )])
dashedLayer.path = path
dashedLayer.lineWidth = 3.0
dashedLayer.strokeColor = UIColor.blue.cgColor
let animation = CABasicAnimation(keyPath: "strokeEnd")
if (height < bounds.size.height){
animation.fromValue = height / bounds.size.height
animation.toValue = 1.0}
else {
animation.fromValue = 1.0
animation.toValue = bounds.size.height / height}
animation.timingFunction = CAMediaTimingFunction.init(name: CAMediaTimingFunctionName.easeInEaseOut)
height = bounds.size.height
animation.duration = 3
dashedLayer.add(animation, forKey: nil)
}