圆形BezierPath填充太多而不是给定的进度值 - iOS Swift

时间:2018-02-18 14:21:42

标签: ios swift uibezierpath cashapelayer cabasicanimation

我有一个循环的UIBezierPath& 2x CAShapeLayers,用于显示我的某个应用中特定里程碑的进度。

问题:当我通过CABasicAnimation为进度设置动画时,进度超出了应该做的范围。

上下文:我在里程碑集合视图中的自定义单元格的子视图中显示此循环视图。

查看层次结构: CollectionView>自定义单元格>子视图> drawRect创建&在那里添加图层。

我的代码:

自定义单元格

在我的自定义单元格中,我设置了currentProgress(现在硬编码用于测试目的)

let placeHolderForProgressView: CircularTrackerView = {
        let ctv = CircularTrackerView()
        ctv.backgroundColor = UIColor.clear
        ctv.translatesAutoresizingMaskIntoConstraints = false
        ctv.currentProgress = 0.5  //set to 0.5 to get a circle filled at 50%
        return ctv
    }()

在CircularTrackerView内

//每当设置单元格时,我都会为进度设置动画,并将currentProgress提供给progressView

var currentProgress: CGFloat = 0.0 {
        didSet {
            animate(to: currentProgress)
            let percent = Int(currentProgress * 100)
            percentLbl.text = "\(percent)%"
        }
    } 


let shapeLayer = CAShapeLayer() //displays the progress 
let trackLayer = CAShapeLayer() //background of the ring

override func draw(_ rect: CGRect) {
    super.draw(rect)

    let center = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
    let circularPath = UIBezierPath(arcCenter: center, radius: frame.size.width / 2, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)

    trackLayer.path = circularPath.cgPath
    trackLayer.strokeColor = UIColor.white.withAlphaComponent(0.2).cgColor
    trackLayer.lineWidth = 5
    trackLayer.fillColor = UIColor.clear.cgColor
    trackLayer.lineCap = kCALineCapRound
    layer.addSublayer(trackLayer)

    shapeLayer.path = circularPath.cgPath
    shapeLayer.strokeColor = UIColor.white.cgColor
    shapeLayer.lineWidth = 5
    shapeLayer.strokeEnd = 0
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.lineCap = kCALineCapRound
    layer.addSublayer(shapeLayer)

}

private func animate(to progress: CGFloat) {

    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.fromValue = 0.0
    animation.toValue = progress
    animation.duration = 2
    animation.fillMode = kCAFillModeForwards
    animation.isRemovedOnCompletion = false

    shapeLayer.add(animation, forKey: "randomString")

}

输出

这个圈子超出了50%的标记......甚至很难我认为我按照正确的步骤创建了这个(稍微改编自YouTube上的LetsBuildThatApp教程:https://www.youtube.com/watch?v=O3ltwjDJaMk

enter image description here

如果您能提供任何有用的输入,请提前致谢。

1 个答案:

答案 0 :(得分:5)

问题在于你的UIBezierPath /你给它的角度:

let circularPath = UIBezierPath(arcCenter: center, radius: frame.size.width / 2, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)

差异endAngle - startAngle2.5 * PI,但只应为2 * PI。如果2.5 * PI表示strokeEnd 0.5 1.25 * PI导致endAngle被抚摸。

解决方案,0.5 * PI减少let circularPath = UIBezierPath(arcCenter: center, radius: frame.size.width / 2, startAngle: -0.5 * CGFloat.pi, endAngle: 1.5 * CGFloat.pi, clockwise: true)

do {
     let fetchedData = try JSONSerialization.jsonObject(with: data!, options: .mutableLeaves) as! Dictionary<String,AnyObject>
     print(fetchedData)

     for eachFetchedJourney in fetchedData{
         let eachJourney = eachFetchedJourney as! [String: Any]
         let line = eachJourney["line"] as! String
         let description = eachJourney["description"] as! String

         self.fetchedJourneys.append(Journey(line: line, description: description))
         print(fetchedData)
     }
     self.journeysTableView.reloadData()
 }