ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SwiftUI LongPressGesture 를 사용한 Fingerprint Button
    SwiftUI 2020. 8. 25. 05:27
    struct FingerprintButton: View {
        //롱프레스  제스처 상태
        @GestureState var press = false
        //롱프레스 제스쳐 완료 상태 체크
        @State var completed = false
        var body: some View {
            //3개의 이미지 와 원형 상태바 레이어용 ZStack
            ZStack {
                //1. 기본 배경 - 완료시 사라짐
                Image("fingerprint1")
                    .opacity(completed ? 0 : 1)
                    .scaleEffect(completed ? 0 : 1)
                
                //2. 진행 중에 위로 이동하면서 애니메이션
                Image("fingerprint2")
                    .clipShape(
                        Circle()
                            .offset(y: press ? 0 : 50)
                    )
                    .animation(.easeOut)
                
                //3. 완료 시 커지면서 화면에 보여짐
                Image(systemName: "checkmark.circle.fill")
                    .font(.system(size: 44, weight: .light))
                    .foregroundColor(Color(#colorLiteral(red: 0.5175917745, green: 0.549059689, blue: 0.8116646409, alpha: 1)))
                    .opacity(completed ? 1 : 0)
                    .scaleEffect(completed ? 1 : 0)
                
                //진행 상태 바
                Circle()
                    .trim(from: press ? 0.001 : 1, to: 1)
                    .stroke(Color(#colorLiteral(red: 0.5568627715, green: 0.3529411852, blue: 0.9686274529, alpha: 1)), style: StrokeStyle(lineWidth: 5, lineCap: .round))
                    .frame(width: 88, height: 88)
                    .rotationEffect(Angle(degrees: 90))
                    .rotation3DEffect(Angle(degrees: 180), axis: (x: 1, y: 0, z: 0))
                    .animation(.easeInOut)
            }
            .frame(width: 120, height: 120)
            .background(
                ZStack {
                    LinearGradient(gradient: Gradient(colors: [Color(#colorLiteral(red: 0.5764705882, green: 0.7098039216, blue: 0.8823529412, alpha: 1)), Color(#colorLiteral(red: 0.9647058824, green: 0.9607843137, blue: 0.9607843137, alpha: 1))]), startPoint: .topLeading, endPoint: .bottomTrailing)
                        .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
                }
                
            )
            //위쪽 광원
            .shadow(color: Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)), radius: 20, x: -20, y: -20)
            //아래쪽 음영
            .shadow(color: Color(#colorLiteral(red: 0.5764705882, green: 0.7098039216, blue: 0.8823529412, alpha: 1)), radius: 20, x: 20, y: 20)
            
            //Long Press Gesture 이벤트 처리
            .gesture(LongPressGesture()
                        .updating($press){ (currentState, gestureState, _) in
                            gestureState = currentState
                        }
                        .onEnded { _ in
                            self.completed = true
                            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                                self.completed = false
                            }
                            //self.press.toggle()
                        }
            )
        }
    }

     

    실행 결과

    댓글

Designed by Tistory.