重置UIProgressView并立即使用Swift 3开始制作动画

时间:2016-11-14 12:33:00

标签: ios swift swift3 nstimer uiprogressview

我有一个像Snapchat和Instagram故事一样的进度视图。进度视图到达结束或点击按钮后,我的内容会发生变化。

我正在重置内容更改时的进度视图。一切都按预期工作,而没有干预。但是当点击下一个按钮时,进度视图不会再次开始,直到另一个循环执行。

您可以快速查看video here

我在研究期间偶然发现this question,我有相同的情况,但我无法将该原则应用于swift 3的新手。

这是我的代码,任何帮助都将受到高度赞赏:

func startTimer(){
    self.timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(myVievController.nextItem), userInfo: nil, repeats: false)
}

func updateProgressBar() {
    self.progressView.setProgress(1.0, animated: false)
    UIView.animate(withDuration: 2.8, animations: {() -> Void in
        self.progressView.layoutIfNeeded()
    }, completion: { finished in
        if finished {
            self.progressView.setProgress(0, animated: false)
        }
    })
}

func nextItem(){
    // ...
    self.updateUI(item: self.myCurrentItem)
    // ...
}

func updateUI(item:MyItem){
    self.updateProgressBar()
    self.timer.invalidate()
    self.startTimer()

    // Clear old item and fill new values etc...
}

@IBAction func nextButtonPressed(_ sender: UIButton) {
    self.nextItem()
}

3 个答案:

答案 0 :(得分:0)

您可能需要这样的内容来更新进度条:self.progressView.setProgress(0, animated: false)

func updateProgressBar() {
    DispatchQueue.main.async {
        self.progressView.setProgress(0.1, animated: false)
    }
    if self.progressView.Progress == 1.0 {
       self.timer.invalidate()
    } else {
       self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(myVievController.updateProgressBar), userInfo: nil, repeats: false)
    }
}

然后您可以使计时器无效并在100%

时停止更新

答案 1 :(得分:0)

也可以使用子类

function renderLabel() {
var label = this.renderer.label("How do I move this center and under the legend.")
  .css({
    width: '180px'
  })
  .attr({
    'stroke': 'silver',
    'stroke-width': 1,
    'r': 5,
    'padding': 10
  })
  .add();

label.align(Highcharts.extend(label.getBBox(), {
  align: 'center',
  x: 0, // offset
  verticalAlign: 'bottom',
  y: 60 // offset
}), null, 'spacingBox');
}

当您需要从头开始再次启动progressView时,可以通过调用class HelloWorld: UIProgressView { func startProgressing(duration: TimeInterval, resetProgress: Bool, completion: @escaping (Void) -> Void) { stopProgressing() // Reset to 0 progress = 0.0 layoutIfNeeded() // Set the 'destination' progress progress = 1.0 // Animate the progress UIView.animate(withDuration: duration, animations: { self.layoutIfNeeded() }) { finished in // Remove this guard-block, if you want the completion to be called all the time - even when the progression was interrupted guard finished else { return } if resetProgress { self.progress = 0.0 } completion() } } func stopProgressing() { // Because the 'track' layer has animations on it, we'll try to remove them layer.sublayers?.forEach { $0.removeAllAnimations() } } } 来使用它。当完成动画时,会调用完成,因此您可以更改视图等。

使用示例:

-startProgressing()

答案 2 :(得分:0)

示例

enter image description here

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var progressView: UIProgressView!

    var timer : Timer?
    var timerCount = 0
    var imageArray : Array<UIImage> = []

    // MARK: - Lifecycle -

    override func viewDidLoad() {

        super.viewDidLoad()

        // create gradient images

        buildImageArray(duration: 3, highlightPercentage: 10.0, mainColor: .green, highlightColor: .yellow, imageWidth: Double(progressView.frame.width))

        // set progressView to first image

        progressView.progressImage = imageArray[0]

        // set progressView progress

        progressView.progress = 0.7

        // schedule timer

        if self.timer == nil {

            self.timer = Timer.scheduledTimer(timeInterval: 1/60, target: self, selector: #selector(updateGradient), userInfo: nil, repeats: true)
            RunLoop.main.add(self.timer!, forMode: .common)

        }

    }

    func buildImageArray(duration: Int, highlightPercentage: Double, mainColor: UIColor, highlightColor: UIColor, imageWidth: Double){

        let keyFrames = duration * 60

        for i in 0..<keyFrames {

            // Drawing code

            let frame = CGRect(x: 0.0, y: 0.0, width: imageWidth, height: 1.0)
            let layer = CAGradientLayer()
            layer.frame = frame
            layer.startPoint = CGPoint(x: 0.0, y: 0.5)
            layer.endPoint = CGPoint(x: 1.0, y: 0.5)

            var colors : [UIColor] = []

            for n in 0..<keyFrames {

                colors.append(mainColor)

            }

            let highlightKeyFrames : Int = Int(floor(Double(keyFrames) * (highlightPercentage/100)))

            // 300 * .3 = 90 kf

            for x in 0..<highlightKeyFrames {

                let p = i+x

                if p < keyFrames {

                    colors[p] = highlightColor

                }

            }

            layer.colors = colors.map { $0.cgColor }

            layer.bounds = frame

            let image = UIImage.imageWithLayer(layer: layer)

            imageArray.append(image)

        }

    }

    // updateGradient

    @objc func updateGradient(){

        // crop image to match progress

        let newWidth = self.progressView.frame.width * CGFloat(progressView.progress)

        let progressImage = imageArray[timerCount].crop(rect: CGRect(x: 0, y: 0, width: newWidth, height: 1))

        progressView.progressImage = progressImage

        // increment timer

        timerCount = timerCount + 1

        if timerCount >= imageArray.count {

            timerCount = 0

        }

    }

}

extension UIImage {

    class func imageWithLayer(layer: CALayer) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.isOpaque, 0.0)
        layer.render(in: UIGraphicsGetCurrentContext()!)
        let img = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return img!
    }

    func crop( rect: CGRect) -> UIImage {
        var rect = rect
        rect.origin.x*=self.scale
        rect.origin.y*=self.scale
        rect.size.width*=self.scale
        rect.size.height*=self.scale

        let imageRef = self.cgImage!.cropping(to: rect)
        let image = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
        return image
    }

}