SwiftUI로 만드는 진행

18836 단어 iOSSwiftSwiftUI

소개



이 기사는 Diverse Advent Calendar 2020의 18 일째 기사입니다.
업무로 몇 가지 진행을 만들었으므로 소개합니다.
비슷한 디자인의 프로그레스를 만들 때는 꼭 활용해 주세요!

GitHub에이 기사의 샘플을 올리고 있습니다.
↓실제로 움직임을 보고 싶은 분은 이쪽
htps : // 기주 b. 코 m / 마사 타카 칸 / 수프 f 드 Prog rs


struct RingProgressView: View {

    var value: CGFloat
    var lineWidth: CGFloat = 6.0
    var outerRingColor: Color = Color.black.opacity(0.08)
    var innerRingColor: Color = Color.orange

    var body: some View {
        ZStack {
            Circle()
                .stroke(lineWidth: self.lineWidth)
                .foregroundColor(self.outerRingColor)
            Circle()
                .trim(from: 0.0, to: CGFloat(min(self.value, 1.0)))
                .stroke(
                    style: StrokeStyle(
                        lineWidth: self.lineWidth,
                        lineCap: .square, // プログレスの角を丸くしたい場合は.round
                        lineJoin: .round
                    )
                )
                .foregroundColor(self.innerRingColor)
                .rotationEffect(.degrees(-90.0))
        }
        .padding(.all, self.lineWidth / 2)
    }
}
@State var value: CGFloat = 0.0

 var body: some View {
    RingProgressView(value: value)
        .frame(width: 150, height: 150)
        .onAppear {
            withAnimation(.linear(duration: 5)) {
                self.value = 1.0
            }
        }        
}



Pie



Shape를 계승해 PieShape라고 하는 것을 만들고 있습니다.
Shape를 자체 제작한 경우 애니메이션이 적용되지 않으므로 animatableData 를 override 해야 합니다.

struct PieProgressView: View {

    var value: CGFloat

    var body: some View {
        ZStack {
            Circle()
                .fill(Color.black.opacity(0.08))
            PieShape(progress: value)
                .fill(Color.orange)
                .rotationEffect(.degrees(-90))
        }
    }
}

struct PieShape: Shape {

    var value: CGFloat

    var animatableData: CGFloat {
        get { value }
        set { value = newValue }
    }

    func path(in rect: CGRect) -> Path {
        Path { path in
            let center = CGPoint(x: rect.midX, y: rect.midY)
            path.move(to: center)
            path.addArc(
                center: center,
                radius: rect.width / 2,
                startAngle: .degrees(0),
                endAngle: .degrees(Double(360 * value)),
                clockwise: false
            )
            path.closeSubpath()
        }
    }
}


@State var value: CGFloat = 0.0

var body: some View {
    PieProgressView(value: value)
        .frame(width: 150, height: 150)
        .onAppear {
            withAnimation(.linear(duration: 5)) {
                self.value = 1.0
            }
        } 
}



광장



Rectangle을 2개 겹쳐 위의 Rectangle의 width를 value에 따라 바꾸는 것으로 실현하고 있습니다.
Square라고 명명하고 있지만 cornerRadius를 지정하여 둥글게 할 수도 있습니다.
struct SquareProgressView: View {

    var value: CGFloat
    var baseColor: Color = Color.black.opacity(0.08)
    var progressColor: Color = Color.orange

    var body: some View {
        GeometryReader { geometry in
            VStack(alignment: .trailing) {
                ZStack(alignment: .leading) {
                    Rectangle()
                        .fill(self.baseColor)
                    Rectangle()
                        .fill(self.progressColor)
                        .frame(minWidth: 0, idealWidth:self.getProgressBarWidth(geometry: geometry),
                               maxWidth: self.getProgressBarWidth(geometry: geometry))
                }
            }
        }
    }

    func getProgressBarWidth(geometry:GeometryProxy) -> CGFloat {
        let frame = geometry.frame(in: .global)
        return frame.size.width * value
    }
}

@State var value: CGFloat = 0.0

var body: some View {

    SquareProgressView(value: value)
        .frame(height: 20)
        //.cornerRadius(10) 角丸も可
        .onAppear {
            withAnimation(.linear(duration: 5)) {
                self.value = 1.0
            }
        } 
}



사이고에게



이번에는 작성한 프로그레스를 3개 소개했습니다.
기본적으로 copipe에서 사용할 수 있다고 생각하므로 꼭 활용하십시오.

좋은 웹페이지 즐겨찾기