I'm trying to disable an implicit animation that is causing the position of my ShapeLayer instance (the small circle at the end of the line) to be animated away from and then back to its location at the end of the line.
A screenshot of the problem is posted here https:// imgur.com/a/I67KjZo
I have tried the approach for using override func action(forKey:) using position as the key, and also the path key. I also tried CATransaction.setDisableActions(true) but that didn't have any apparent effect.
I have been unable to figure out how to solve variations of this problem for almost a month and I would appreciate if someone could help me out here.
When the container (yellow box) is resized, I want its bounds to be animated just as you see here, but I don't want the circle sublayer to "go somewhere else" and come back again just in time for the end of the animation.
Or if disabling an animation is not the best answer here, is there another way I could make the container layer determine the position of its sublayers that won't cause the resize animation disintegrate the arrangement this way?
The full project is here
A screenshot of the problem is posted here https:// imgur.com/a/I67KjZo
I have tried the approach for using override func action(forKey:) using position as the key, and also the path key. I also tried CATransaction.setDisableActions(true) but that didn't have any apparent effect.
I have been unable to figure out how to solve variations of this problem for almost a month and I would appreciate if someone could help me out here.
When the container (yellow box) is resized, I want its bounds to be animated just as you see here, but I don't want the circle sublayer to "go somewhere else" and come back again just in time for the end of the animation.
Or if disabling an animation is not the best answer here, is there another way I could make the container layer determine the position of its sublayers that won't cause the resize animation disintegrate the arrangement this way?
The full project is here
Code Block class ContainerView: UIView { override class var layerClass: AnyClass { return ContainerLayer.self } override func draw(_ rect: CGRect) { } } class ContainerLayer: CALayer, CALayerDelegate { var circle = ShapeLayer() var didSetup = false var figureCenter: CGPoint { return CGPoint(x: self.bounds.midX, y: self.bounds.midY) } var figureDiameter: CGFloat { return min(self.bounds.width, self.bounds.height) } var figureRadius: CGFloat { return figureDiameter / 2 } var strokeWidth: CGFloat { return max(round(figureDiameter / 10), 1) } var circleDiameter: CGFloat { return max(round(figureDiameter / 25), 5) } var circleRadius: CGFloat { return circleDiameter/2 } var locRadius: CGFloat { return figureRadius - circleRadius - strokeWidth } var circleLineWidth: CGFloat = 1 var unitLoc: CGPoint { return CGPoint(x: figureCenter.x + cos(-halfPi) * locRadius, y: figureCenter.y + sin(-halfPi) * locRadius) } override func layoutSublayers() { super.layoutSublayers() ... setup updateCircleBounds() } func setup() { ... self.needsDisplayOnBoundsChange = true } func updateCircleBounds() { self.circle.bounds = CGRect(x: 0, y: 0, width: circleDiameter, height: circleDiameter) self.circle.position = unitLoc self.circle.updatePath() } override func draw(in ctx: CGContext) { ... stroke ctx paths, etc } } class ShapeLayer: CAShapeLayer { var didSetup = false var diameter: CGFloat { return self.bounds.width } var pathOrigin: CGPoint { return CGPoint(x: self.bounds.minX, y: self.bounds.minY) } var pathSize: CGSize {return CGSize(width: self.diameter, height: self.diameter) } var strokeWidth: CGFloat? var fColor: CGColor? var sColor: CGColor? override func layoutSublayers() { super.layoutSublayers() ... setup updatePath() } override func action(forKey key: String) -> CAAction? { print(key) if key == #keyPath(position) { if self.value(forKey:"suppressPositionAnimation") != nil { print("key: \(key)") return nil } } return super.action(forKey:key) } func setup() { ... self.setValue(true, forKey:"suppressPositionAnimation") } func updatePath() { self.path = UIBezierPath(ovalIn: CGRect(origin: pathOrigin, size: pathSize).insetBy(dx: self.lineWidth/2, dy: self.lineWidth/2)).cgPath } }