iOS/Swift

[Swift] 원형 프로그래스 바 구현 (Custom circular progress bar)

HUISOO 2022. 8. 12. 10:19

이 포스트는 원형 프로그래스 바 구현 (Custom circular progress bar)을 설명하기 위한 포스팅입니다 :)

 

 

최종 수정일 - 22. 08. 12 AM 10:30


 

원형 프로그래스바 만들어보기

 

1. 새로운 파일 CircularProgressBar.swift 를 준비합니다.

 

2. CircularProgressBar 에 Class를 생성합니다.

class CircularProgressBar {
    override func draw(_ rect: CGRect) {
        // Code...
    }
}

 

3. 프로그래스 바의 두께와 값을 설정한 변수를 생성해 줍니다. 

- 스토리보드에서 값을 변경하고 싶다면 '@IBInspectable'을 추가합니다. 

@IBInspectable var lineWidth: CGFloat = 3

var value: Double? {
    didSet {
        guard let _ = value else { return }

        // Code..
    }
}

 

4. draw(_:)에서 UIBezierPath를 이용해 프로그래스바의 기초를 그려줍니다.

override func draw(_ rect: CGRect) {
    let bezierPath = UIBezierPath()

    bezierPath.addArc(withCenter: CGPoint(x: rect.midX, y: rect.midY), radius: rect.midX - ((lineWidth - 1) / 2), startAngle: 0, endAngle: .pi * 2, clockwise: true)

    bezierPath.lineWidth = 1
    UIColor.systemGray4.set()
    bezierPath.stroke()
}

  - withCener : 그려줄 곡선의 중심점

  - radius : 곡선의 반지름

  - startAngle : 곡선의 시작점

  - endAngle : 곡선의 종료점

  - clockwise : 시계방향 / 반시계방향

 

5. setProgress(_:) 함수를 만들어서 프로그래스바를 그려줍니다.

func setProgress(_ rect: CGRect) {
    guard let value = self.value else {
        return
    }

	// TableView나 CollectionView에서 재생성 될때 계속 추가되는 것을 막기 위해 제거
    self.subviews.forEach { $0.removeFromSuperview() }
    self.layer.sublayers?.forEach { $0.removeFromSuperlayer() }

    let bezierPath = UIBezierPath()

    bezierPath.addArc(withCenter: CGPoint(x: rect.midX, y: rect.midY), radius: rect.midX - ((lineWidth - 1) / 2), startAngle: -.pi / 2, endAngle: ((.pi * 2) * value) - (.pi / 2), clockwise: true)

    let shapeLayer = CAShapeLayer()

    shapeLayer.path = bezierPath.cgPath
    shapeLayer.lineCap = .round	// 프로그래스 바의 끝을 둥글게 설정

    let color: UIColor = .systemBlue

    shapeLayer.strokeColor = color.cgColor
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.lineWidth = lineWidth

    self.layer.addSublayer(shapeLayer)

	// 프로그래스바 중심에 수치 입력을 위해 UILabel 추가
    let label = UILabel()
    label.text = String(Int(value * 100))
    label.textColor = .label
    label.font = .systemFont(ofSize: 8, weight: .light)

    self.addSubview(label)

    label.translatesAutoresizingMaskIntoConstraints = false
    label.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
    label.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
}

 

6. value 값이 변경될 때 프로그래스바를 갱신하도록 하기

var value: Double? {
    didSet {
        guard let _ = value else { return }
        setProgress(self.bounds)
    }
}

 

7. 사용해봅니다.

@IBOutlet weak var circularProgressBar: CircularProgressBar!

circularProgressBar.value = 0.84

적용 사진