簡體   English   中英

IOS 用 CAShapeLayer 自定義進度條

[英]IOS custom progress bar with CAShapeLayer

我怎樣才能用弧結束的文字創建一個像這張圖片的自定義弓

彩虹加載圖像

這是我當前的代碼和當前結果

        let center = view.center
        let circularPath = UIBezierPath(arcCenter: center, radius: 120, startAngle:  CGFloat.pi , endAngle: CGFloat.pi*2, clockwise: true)

        
        let greyLayer = CAShapeLayer()
        greyLayer.strokeColor = greyColor
        greyLayer.lineWidth = lineWidth
        greyLayer.path = circularPath.cgPath
        greyLayer.lineCap = .round
        greyLayer.fillColor = UIColor.clear.cgColor
        greyLayer.shadowColor = UIColor.black.cgColor
        greyLayer.shadowOpacity = 1
        greyLayer.shadowOffset = .zero
        greyLayer.shadowRadius = 2
        view.layer.addSublayer(greyLayer)


        shapeLayer.strokeColor = bowColor
        shapeLayer.lineWidth = lineWidth
        shapeLayer.path = circularPath.cgPath
        shapeLayer.lineCap = .round
        shapeLayer.strokeEnd =  0
        shapeLayer.fillColor = UIColor.clear.cgColor
        view.layer.addSublayer(shapeLayer)
        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))

        let label = UILabel()
        label.text = "Best"
        label.textAlignment = .center
        label.textColor = .red
        label.font = UIFont.boldSystemFont(ofSize: 30)
        
                
        view.addSubview(label)
        
        view.layer.addSublayer(label.layer)
        label.translatesAutoresizingMaskIntoConstraints = false
        
        label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        
        label.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        
        label.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive  = true
        
        label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
         

當前結果我想在圓弧的末端添加一個圓形並像上圖一樣動畫,我不知道如何實現這個在此處輸入圖像描述

為了讓你開始...

您的弧線從.pi變為.pi*2 ...但不是.pi*2它可能會幫助您將其視為:

  • 弧從.pi開始,即“9 點鍾”
  • 完成進度將跨越到“3 點鍾”,即添加.pi到起始角度

完成進度為.pi加上.pi * progressPercent

因此,要獲得endAngle

  • 25% 的進度是.pi + ((25.0 / 100.0) *.pi)
  • 50% 的進度是.pi + ((50.0 / 100.0) *.pi)
  • 83% 的進度是.pi + ((83.0 / 100.0) *.pi)

編碼,你會做這樣的事情:

    let score = 83
    
    let endAngle: CGFloat = .pi + ((CGFloat(score) / 100.0) * .pi)
    
    let center = view.center
    let circularPath = UIBezierPath(arcCenter: center, radius: 120, startAngle: .pi, endAngle: endAngle, clockwise: true)

現在你的弧線跨越了 83% 的“半圓”。

要在弧的末端添加 label,您可以從路徑中獲取該點:

    // point at end of arc
    let endPoint: CGPoint = circularPath.currentPoint
    

您可以使用該點指向 position 您的 label(或自定義“氣球”label 視圖)。

這是您的代碼,稍作修改以添加一個score值和一個progressLabel

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemTeal
        
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        let greyColor = UIColor.gray.cgColor
        let bowColor = UIColor.systemPink.cgColor
        let lineWidth: CGFloat = 12
        let shapeLayer = CAShapeLayer()
        
        let score = 83
        
        let endAngle: CGFloat = .pi + (.pi * (CGFloat(score) / 100.0))
        
        let center = view.center
        let circularPath = UIBezierPath(arcCenter: center, radius: 120, startAngle: .pi, endAngle: endAngle, clockwise: true)

        // point at end of arc
        let endPoint: CGPoint = circularPath.currentPoint
        
        let greyLayer = CAShapeLayer()
        greyLayer.strokeColor = greyColor
        greyLayer.lineWidth = lineWidth
        greyLayer.path = circularPath.cgPath
        greyLayer.lineCap = .round
        greyLayer.fillColor = UIColor.clear.cgColor
        greyLayer.shadowColor = UIColor.black.cgColor
        greyLayer.shadowOpacity = 1
        greyLayer.shadowOffset = .zero
        greyLayer.shadowRadius = 2
        view.layer.addSublayer(greyLayer)
        
        
        shapeLayer.strokeColor = bowColor
        shapeLayer.lineWidth = lineWidth
        shapeLayer.path = circularPath.cgPath
        shapeLayer.lineCap = .round
        shapeLayer.strokeEnd =  0
        shapeLayer.fillColor = UIColor.clear.cgColor
        view.layer.addSublayer(shapeLayer)
        //view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
        
        let label = UILabel()
        label.text = "Best"
        label.textAlignment = .center
        label.textColor = .red
        label.font = UIFont.boldSystemFont(ofSize: 30)
        
        
        view.addSubview(label)
        
        view.layer.addSublayer(label.layer)
        label.translatesAutoresizingMaskIntoConstraints = false
        
        label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        
        label.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        
        label.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive  = true
        
        label.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        
        let progressLabel = UILabel()
        progressLabel.backgroundColor = .cyan
        progressLabel.text = "\(score)%"
        progressLabel.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(progressLabel)
        progressLabel.bottomAnchor.constraint(equalTo: view.topAnchor, constant: endPoint.y).isActive = true
        progressLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: endPoint.x).isActive = true

    }
}

結果:

在此處輸入圖像描述

如果您想“動畫化”進度弧和 label,那將需要更多的工作......但這是一個很好的學習練習讓您承擔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM