가이드

SwiftUI에서 원형 프로그래스 뷰 만들기

Sunghyun Kim 2022. 8. 20. 23:26

SwiftUI에서 원형 프로그래스 뷰 만들기

원형 뷰 만들기

우선 원형 틀을 추가한다.

struct CircleProgressView: View {
    var body: some View {
        Circle()
            .stroke(Color.red.opacity(0.5), lineWidth: 5)
    }
}

Image.png

그리고 실제 프로그래스를 나타낼 뷰를 ZStack으로 올린다. trim 모디파이어를 사용해 원을 잘라서 사용할 수 있다.

ZStack {
    Circle()
        .stroke(Color.red.opacity(0.5), lineWidth: 5)
    Circle()
        .trim(from: 0, to: 0.25) // <-
        .stroke(Color.red, lineWidth: 5)
}

Image.png

또한 현재 원이 잘리는 시작점이 90도 회전해 있기 때문에 rotationEffect를 사용해 회전시켜 준다.

ZStack {
    Circle()
        .stroke(Color.red.opacity(0.5), lineWidth: 5)
    Circle()
        .trim(from: 0, to: 0.25)
        .stroke(Color.red, lineWidth: 5)
        .rotationEffect(.degrees(-90)) // <-
}

진행도 모양을 둥글게 처리하고 싶다면 stroke style을 적용하여 둥글게 처리할 수 있다.

Circle()
    .trim(from: 0, to: 0.25)
    .stroke(Color.red, style: StrokeStyle( // <-
        lineWidth: 5, lineCap: .round
    ))
    .rotationEffect(.degrees(-90))

Image.png

이제 값을 입력받아 프로그래스가 움직이도록 변경해주면 된다.

struct CircularProgressView: View {
    var progress: Double // <-

    var body: some View {
        ZStack {
            Circle()
                .stroke(Color.red.opacity(0.5), lineWidth: 5)
            Circle()
                .trim(from: 0, to: CGFloat(progress)) // <-
                .stroke(Color.red, style: StrokeStyle(
                    lineWidth: 5, lineCap: .round
                ))
                .rotationEffect(.degrees(-90))
        }
    }
}

화면 기록 2022-08-19 오후 4.56.30.gif

struct ContentView: View {
    @State var progress = 0.0
    var body: some View {
        VStack {
            CircularProgressView(progress: progress)
                .frame(width: 70, height: 70)
            Slider(value: $progress, in: 0...1)
        }
    }
}

ProgressView에 적용 가능하도록 수정하기 (iOS 14+)

ProgressViewStyle을 사용하여 여러 ProgressView에 걸쳐 동시에 해당 스타일을 적용할 수 있다.

struct CircularProgressViewStyle: ProgressViewStyle {
    func makeBody(configuration: Configuration) -> some View {
        let progress = configuration.fractionCompleted ?? 0
        CircularProgressView(progress: progress)
    }
}
var body: some View {
    VStack {
        ProgressView(value: 0.25)
        ProgressView(value: 0.75)
    }
    .frame(width: 70)
    .progressViewStyle(CircularProgressViewStyle())
}

Image.png