2017-05-12 63 views
0

工作,我有一個進度法hereCABasicAnimation上CAShapeLayer不通路改變

func progress(incremented : CGFloat){ 
    if incremented <= self.bounds.width{ 
     self.progressLayer.removeFromSuperlayer() 
     let originBezierPathProg = UIBezierPath(roundedRect: CGRect(x:0, y:0, width:0, height:self.bounds.height) , cornerRadius: self.viewCornerRadius) 
     originBezierPathProg.close() 

     let newBezierPathProg = UIBezierPath(roundedRect: CGRect(x:0, y:0, width:incremented, height:self.bounds.height) , cornerRadius: self.viewCornerRadius) 
     bezierPathProg.close() 

     self.progressLayer.path = originBezierPathProg.cgPath 
     self.borderLayer.addSublayer(self.progressLayer) 

     let animation = CABasicAnimation(keyPath: "path") 
     animation.fromValue = originBezierPathProg.cgPath 
     animation.toValue = newBezierPathProg.cgPath 
     animation.duration = 1 
     self.progressLayer.add(animation, forKey: animation.keyPath) 

     self.progressLayer.path = newBezierPathProg.cgPath 
    } 
} 

我試圖使動畫的方式進度條的進展。但是當我打電話給progress(100)時,它只是在沒有動畫的情況下渲染欄。

我該如何解決?

更新:根據Rob的建議創建了MCVE:https://github.com/utkarsh2012/ProgressBarTest。我期待進度條動畫從寬度= 0 WIDTH = X(比方說60)

類似於這樣的問題CABasicAnimation with CALayer path doesn't animate

+0

雖然這[可能會收緊一點](https://gist.github.com/robertmryan/eb8a9a422ad3820e3eb20fe143be3893),它對我來說很有效。所以問題在於你如何調用它(太早,太頻繁,從後臺線程),或者你的'bounds'或'incrementated'值是''if'語句失敗。我們需要問題的可生成的例子。 – Rob

+0

讓我想出一個有這個問題的簡單項目。幾個小時以來一直在掙扎,我認爲真正的問題是它從UIView的var ididSet被調用(可能爲時過早?)。之後我也會做佈局。看看setupView:https://github.com/TwoPence/TwoPence/blob/milestone/TwoPence/MilestoneFutureView.swift – zengr

+0

很難說。這裏有一些不相關的東西,但同時,還不足以重現問題。如果您希望我們提供幫助,我們確實需要[MCVE](http://stackoverflow.com/help/mcve),即向我們展示如何創建空白項目,插入顯示您問題的最少量代碼。或者,如果您想自己診斷問題,請添加調試代碼,以檢查(a)確保它在主線程上發生; (b)當'progress(增加:)'被調用時,你認爲'bounds'是' (c)「遞增」值是多少。 – Rob

回答

1

progress方法最初是在你的問題中所示是好的。問題在於你如何使用它。已經有人說過了,讓我們通過MCVE。

your MCVE,有幾件事情防止動畫,即:

  1. progress方法如下:

    func progress(incremented: CGFloat) { 
        if incremented <= bounds.width { 
         let toPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: incremented + 100, height: bounds.height), cornerRadius: viewCornerRadius) 
    
         progressLayer.path = toPath.cgPath 
         borderLayer.addSublayer(progressLayer) 
    
         let animation = CABasicAnimation(keyPath: "path") 
         animation.fromValue = self.progressLayer.path 
         animation.toValue = toPath.cgPath 
         animation.duration = 3 
         progressLayer.add(animation, forKey: animation.keyPath) 
        } 
    } 
    

    即設置path成爲新的路徑,然後從那個動畫到新的路徑(即從同一路徑進行動畫)。因此,沒有動畫。

    在將path更改爲新的「結束狀態」並啓動動畫之前,請保存舊路徑。使用該保存的路徑作爲動畫的fromValue

  2. value財產被調用layoutSubviews

    var value: Int? { 
        didSet { 
         progress(value: value!) 
         self.layoutSubviews() 
        } 
    } 
    

    不要直接調用layoutSubviews()

  3. 視圖控制器是做以下:

    override func viewDidLoad() { 
        super.viewDidLoad() 
        // Do any additional setup after loading the view, typically from a nib. 
        let view = DetailView(frame: self.view.frame) 
        view.value = 60 
        self.containerView.addSubview(view) 
    } 
    

    不要試圖在viewDidLoad啓動動畫。在視圖生命週期中這太早了。改用viewDidAppear(或其他)。在viewDidLoad中執行此操作通常在視圖生命週期中爲時尚早。

  4. 相關人士認爲viewDidLoad代碼,你改變DetailView(從而引發了動畫)的value您已經將其添加到視圖層次結構之前。


看到這裏https://github.com/robertmryan/ProgressBarTest的修補程序。

+0

哇,謝謝!很多事情都出錯了!非常感謝Github PR!下一次你在SF,咖啡我:) – zengr

+1

或者,如果你在洛杉磯,看看我。 – Rob

+0

動畫工作,但現在它導致一個奇怪的行爲,其中數據從標籤中的默認值更改爲實際值。 http://imgur.com/a/zqn2o可能是後續問題,如果我無法找到修復。 – zengr