UIView с подклассом CAShapeLayer не анимируется во время вращения устройства

TL; DR: По сути, моя проблема такая же, как у этот вопрос.

Я последовал отличному ответу (как всегда) Роба Мэйоффа. Моя проблема в том, что я использую не CAGradientLayer, а CAShapeLayer, и это не работает.

Я использую CAShapeLayer вместо UIBezierPath, потому что мне нужно анимировать цвет и тень контура.

Правда, проблема касается формы пути при вращении устройства: анимация CAShapeLayer выглядит ужасно, на самом деле даже не анимируется, а просто сразу подстраивает путь к новым границам.

Раньше я добавлял CAShapeLayer в качестве подслоя, но, читая здесь некоторые ответы, я попытался создать подкласс UIView и установить его слой на CAShapeLayer, чтобы представление автоматически управляло анимацией вращения, но результат тот же.

Если я рисую с использованием UIBezierPath, он отлично работает (но, к сожалению, мне нужны CAShapeLayer функции)

Вот мой код:

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
        
    }
}
 

Поворачивая устройство, вы увидите разницу между UIBezierPath красным и CAShapeLayer синим. Я уверяю, что с моим реальным путем анимация с CAShapeLayer ужасна.

Я что-то упускаю?

Всем большое спасибо.


person J.Williams    schedule 17.01.2015    source источник
comment
вы можете поделиться своим кодом анимации?   -  person Vitalii Gozhenko    schedule 17.01.2015
comment
Привет @VitaliyGozhenko, кода анимации нет :) Я имею в виду, что анимация автоматически выполняется представлением при повороте устройства. Я добавлю ссылку на аналогичный вопрос, чтобы вы поняли   -  person J.Williams    schedule 17.01.2015
comment
@ J.Williams: Тебе удалось найти решение твоей проблемы? При повороте устройства я обнаружил, что настраиваемое представление с CAShapeLayer в качестве корневого слоя не решает проблему изменения размера представления при изменении ориентации устройства.   -  person Wael Showair    schedule 21.01.2019


Ответы (1)


Этот код в вашем drawRect не может быть анимирован:

        UIColor.redColor().set()
        bezierPath.lineWidth = 20
        bezierPath.stroke()

Вот почему ваше изображение partially перерисовывается при повороте устройства

Вам понадобится что-то вроде этого:

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
    }

}
person Vitalii Gozhenko    schedule 17.01.2015