如何使用Swift在UIView中使圆形进度条居中?

时间:2020-05-15 21:20:08

标签: swift uiview storyboard

仅在确保圆形进度条始终位于与其关联的UIView的中心时,我就有很多困难。

正在发生的事情:

enter image description here

忽略灰色区域,这只是占位符卡上的UIView。红色是我添加为UIView出口的UIViewController

下面是我制作的类的代码:

class CircleProgress: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupView()
    }

    var progressLyr = CAShapeLayer()
    var trackLyr = CAShapeLayer()

    var progressClr = UIColor.red {
       didSet {
          progressLyr.strokeColor = progressClr.cgColor
       }
    }

    var trackClr = UIColor.black {
       didSet {
          trackLyr.strokeColor = trackClr.cgColor
       }
    }

    private func setupView() {
        self.backgroundColor = UIColor.red

        let centre = CGPoint(x: frame.size.width/2, y: frame.size.height/2)

        let circlePath = UIBezierPath(arcCenter: centre,
                                      radius: 10,
                                      startAngle: 0,
                                      endAngle: 2 * CGFloat.pi,
                                      clockwise: true)

        trackLyr.path = circlePath.cgPath
        trackLyr.fillColor = UIColor.clear.cgColor
        trackLyr.strokeColor = trackClr.cgColor
        trackLyr.lineWidth = 5.0
        trackLyr.strokeEnd = 1.0

        layer.addSublayer(trackLyr)
    }
}

目标只是使黑圈的所有4个边缘接触红场的边缘。

我们非常感谢您的帮助。我认为这一定太明显了,但是今晚花费了我太多时间。 :)

3 个答案:

答案 0 :(得分:1)

一些建议:

  1. 我建议使这个public class BaseController { @Autowired public Facade facade; /** * Inject Services from Spring */ public void setFacade(Facade facade){ this.facade = facade; } } 占据整个视野。如果您希望在视图中插入它,那么可以为它添加一个属性。在下面的示例中,我创建了一个名为CircularProgress的属性来捕获此值。

  2. 请确保更新inset中的路径。特别是如果您使用约束,则希望它对大小变化做出响应。因此,请从layoutSubviews添加这些图层,但要在init中更新路径。

  3. 不引用layoutSubviews(这是超级视图坐标系中的位置)。使用frame。然后将其插入线宽的一半,这样圆就不会超出视图的范围。

  4. 您创建了一个进度颜色和进度层,但未使用任何一个。我猜想您希望在曲目中显示进度。

  5. 您正在抚摸从0到2π的路径。人们倾向于期望这些圆形进度视图从-π/ 2(12点钟)开始,然后发展到3π/ 2。因此,我已经更新了使用这些值的路径。但是,请使用您想要的任何东西。

  6. 如果需要,可以将其设置为bounds,如果要在IB中呈现此效果。

因此,将其组合在一起,您将得到:

@IBDesignable

结果是:

enter image description here

答案 1 :(得分:0)

更新此功能

private func setupView() {
        self.backgroundColor = UIColor.red

        let centre = CGPoint(x: bounds.midX, y: bounds.midY)

        let circlePath = UIBezierPath(arcCenter: centre,
                                      radius: bounds.maxX/2,
                                      startAngle: 0,
                                      endAngle: 2 * CGFloat.pi,
                                      clockwise: true)

        trackLyr.path = circlePath.cgPath
        trackLyr.fillColor = UIColor.clear.cgColor
        trackLyr.strokeColor = trackClr.cgColor
        trackLyr.lineWidth = 5.0
        trackLyr.strokeEnd = 1.0

        layer.addSublayer(trackLyr)
    }

答案 2 :(得分:0)

问题是创建对象时没有传递帧。无需更改代码。当然,您必须将宽度和高度更改为任意值。

这是一个例子...

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = .white

        // Add circleProgress
        addCircleProgress()
    }

    private func addCircleProgress() {
        let circleProgress = CircleProgress(frame: CGRect(x: self.view.center.x - 50, y: self.view.center.x - 50, width: 100, height: 100))
        self.view.addSubview(circleProgress)
    }
}

class CircleProgress: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    var progressLyr = CAShapeLayer()
    var trackLyr = CAShapeLayer()

    var progressClr = UIColor.red {
        didSet {
            progressLyr.strokeColor = progressClr.cgColor
        }
    }

    var trackClr = UIColor.black {
        didSet {
            trackLyr.strokeColor = trackClr.cgColor
        }
    }

    private func setupView() {
        self.backgroundColor = UIColor.red

        let centre = CGPoint(x: frame.size.width/2, y: frame.size.height/2)

        let circlePath = UIBezierPath(arcCenter: centre,
                                      radius: 50,
                                      startAngle: 0,
                                      endAngle: 2 * CGFloat.pi,
                                      clockwise: true)

        trackLyr.path = circlePath.cgPath
        trackLyr.fillColor = UIColor.clear.cgColor
        trackLyr.strokeColor = trackClr.cgColor
        trackLyr.lineWidth = 5.0
        trackLyr.strokeEnd = 1.0

        layer.addSublayer(trackLyr)
    }
}

enter image description here