Reputation: 1435
TL;DR: Basically, my problem is the same as this question.
I followed the excellent answer (as always) by Rob Mayoff. My problem is that I am not using a CAGradientLayer
but a CAShapeLayer
and it does not work.
I use a CAShapeLayer
instead of a UIBezierPath
because I need to animate the path colour and shadow.
Though, the problem regards the shape of the path when the device rotates: the animation of CAShapeLayer
looks awful, in fact, it does not even animate, It just immediately arrange the path to the new bounds.
I used to add the CAShapeLayer
as a sublayer, but reading some answers here I tried to subclass UIView
and set its layer to CAShapeLayer
so that the view would manage the rotation animation automagically, but the result is the same.
If I draw using UIBezierPath
it does work perfectly (but I need CAShapeLayer
features, unfortunately)
Here is my code:
import UIKit
class CaShapeLayerView: UIView {
override class func layerClass () -> AnyClass{
return CAShapeLayer.self
}
override func drawRect(rect: CGRect) {
var bezierPath = UIBezierPath()
// create a random scribble :)
bezierPath.moveToPoint(CGPoint(x: 0, y: 0))
bezierPath.addCurveToPoint(CGPoint(x:self.bounds.width, y:self.bounds.height), controlPoint1: CGPoint(x: self.bounds.width/50, y: self.bounds.height/2), controlPoint2: CGPoint(x: self.bounds.width/40, y: self.bounds.height/8*10))
// draw UIBezierPath
UIColor.redColor().set()
bezierPath.lineWidth = 20
bezierPath.stroke()
// draw CAShapeLayer
var shapeLayer = self.layer as CAShapeLayer
shapeLayer.strokeColor = UIColor.blueColor().CGColor
shapeLayer.fillColor = nil
shapeLayer.lineWidth = 16
shapeLayer.path = bezierPath.CGPath
}
}
Rotating the device you will see the difference between the UIBezierPath
in red and the CAShapeLayer
in blue.
I assure the with my actual path the "animation" with CAShapeLayer
is awful.
Am I missing something?
Thank you very much everybody.
Upvotes: 1
Views: 489
Reputation: 9354
This code at your drawRect
isn't animatable:
UIColor.redColor().set()
bezierPath.lineWidth = 20
bezierPath.stroke()
That's why your image partially
redraw on device rotation
You need something like this:
class CAShapeLayerView: UIView {
var firstShapeLayer, secondShapeLayer:CAShapeLayer
required init(coder aDecoder: NSCoder) {
firstShapeLayer = CAShapeLayer()
secondShapeLayer = CAShapeLayer()
super.init(coder: aDecoder)
}
override class func layerClass () -> AnyClass{
return CAShapeLayer.self
}
override func awakeFromNib() {
self.firstShapeLayer.lineWidth = 20
self.firstShapeLayer.strokeColor = UIColor.redColor().CGColor
self.firstShapeLayer.fillColor = nil
self.secondShapeLayer.strokeColor = UIColor.blueColor().CGColor
self.secondShapeLayer.fillColor = nil
self.secondShapeLayer.lineWidth = 16
self.layer.addSublayer(self.firstShapeLayer)
self.layer.addSublayer(self.secondShapeLayer)
}
override func layoutSubviews() {
super.layoutSubviews();
var bezierPath = UIBezierPath()
// create a random scribble :)
bezierPath.moveToPoint(CGPoint(x: 0, y: 0))
bezierPath.addCurveToPoint(CGPoint(x:self.bounds.width, y:self.bounds.height), controlPoint1: CGPoint(x: self.bounds.width/50, y: self.bounds.height/2), controlPoint2: CGPoint(x: self.bounds.width/40, y: self.bounds.height/8*10))
self.firstShapeLayer.path = bezierPath.CGPath
self.secondShapeLayer.path = bezierPath.CGPath
}
}
Upvotes: 1