KoreaMango 나무

[iOS App Dev Tutorials] SwiftUI - Drawing 본문

iOS/iOS App Dev Tutorials

[iOS App Dev Tutorials] SwiftUI - Drawing

KoreaMango 2022. 5. 18. 21:30
 

Apple Developer Documentation

 

developer.apple.com

1. Drawing the Timer View

Section 1. Create the Meeting Timer View

아무런 기능이 없던 원래 원을 없애고 작업률을 나타내는 새로운 원과 발표자의 이름을 포함하는 View를 넣을 것이다.

struct MeetingTimerView: View {
    let speakers: [ScrumTimer.Speaker]
    let theme: Theme
    
    private var currentSpeaker: String {
        speakers.first(where: { !$0.isCompleted })?.name ?? "Someone"
    }
    
    var body: some View {
        Circle()
            .strokeBorder(lineWidth: 24)
            .overlay {
                VStack {
                    Text(currentSpeaker)
                        .font(.title)
                    Text("is speaking")
                }
                .accessibilityElement(children: .combine)
                .foregroundStyle(theme.accentColor)
            }
    }
}

struct MeetingTimerView_Previews: PreviewProvider {
    static var speakers: [ScrumTimer.Speaker] {
        [ScrumTimer.Speaker(name: "Bill", isCompleted: true), ScrumTimer.Speaker(name: "Cathy", isCompleted: false)]
    }
    
    static var previews: some View {
        MeetingTimerView(speakers: speakers, theme: .yellow)
    }
}

우선 원과 발표자를 넣을 MeetingTimerView를 생성한다.

그리고 원을 그리고, 원 안에 텍스트를 overlay 한다.

발표자와 테마 프로퍼티를 만들고 preview에 업데이트한다. preview에 정적 변수를 만들면 UI를 개발하는 동안 도움이 될 것이다.

발표자 배열에서 첫 번째 발표자를 뽑아내는 프로퍼티를 만든다. 그리고 이 프로퍼티를 사용해 원 안에 Text에 넣는다.

struct MeetingView: View {
   ...
    
var body: some View {
    ZStack {
        RoundedRectangle(cornerRadius: 16)
            .fill(scrum.theme.mainColor)
        VStack {
            MeetingHeaderView(...)
            MeetingTimerView(...)
            MeetingFooterView(...)
				}
    }
    ...
}

struct MeetingView_Previews: PreviewProvider {...}

그리고 MeetingView에 원 자리를 지우고, MeetingTimerView를 추가한다.

Section 2. Draw an Arc Segment

이 섹션에서는 한 발표자의 시간을 나타내는 원의 일부를 추적하는 단일 호 세그먼트를 만들 것이다.

호를 작성하려면 Shape 프로토콜을 준수하는 구조를 작성해야한다. Shape 프로토콜에는 path(in:) 이라는 필수 기능이 있다. path(in:) 함수와 해당 함수 내부의 경로를 계산하는데 사용할 추가 속성을 작성한다.

호의 모양은 발표자의 수에 따라 호의 길이를 계산한다. 현재 발표자의 인덱스 번호를 사용해서 원을 따라 호가 시작되고 멈추는 위치를 알 수 있다.

  1. 계산에 사용할 speakerIndex와 totalSpeakers를 선언한다.
  2. 360도를 전체 발표자로 나눈 변수를 생성한다.
  3. 2번 변수에 index를 곱해서 시작 각도와 끝 각도를 구한다.
  4. 지름과 반지름, 중심을 정하고 path에 addArc 해준다.

Section 3. Draw the Progress Ring

.overlay  {
    ForEach(speakers) { speaker in
        if speaker.isCompleted, let index = speakers.firstIndex(where: { $0.id == speaker.id }) {
            SpeakerArc(speakerIndex: index, totalSpeakers: speakers.count)
                .rotation(Angle(degrees: -90))
                .stroke(theme.mainColor, lineWidth: 12)
        }
    }
}

MeetingTimerView의 Circle에 한번더 overlay를 해서 앞에 원이 하나 더 온다.

발표자가 완료가 되었을 경우 SpeakerArc를 실행시키면서 호를 그리게 된다. 시작점을 12시 방향에 맞추기 위해 rotate -90을 해주었고 테두리 색과 두께를 정해주었다.