Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
SwiftUI/SwiftUI(Intermediate)

10. LongPressGesture 길게 누르기

by Toughie 2023. 5. 25.

⭐️LongPressGesture 길게 누르기⭐️

 

tapGesture의 경우 탭 하는 순간  바로 어떤 액션이 실행되는데,

일정 시간 이상 누르고 있어야 액션이 실행되도록 해야 하는 경우에 LongPressGesture를 활용할 수 있다.

대부분의 앱에서는 크게 사용할 일이 없을 거 같지만..게임이나 특수한 상황에서 사용할 수도 있겠다는 생각.

LongPressGesture는 크게 3가지 정도를 고려할 수 있겠다.

1. 얼마나 눌러야 하는가?

2. 누르고 있는가?

3. 다 눌렀는가? 

//  Created by Toughie on 2023/05/25.
//

import SwiftUI

struct LongPressGesture: View {
    //누르고 있는지 판단하기 위한 프로퍼티
    @State var isPressed: Bool = false
    //정해진 시간만큼 다 눌렀는지 판단하기 위한 프로퍼티
    @State var isCompleted: Bool = false
    
    var body: some View {
        
        VStack {
            Rectangle()
            //정해진 시간만큼 다 누르면 색상 변경
                .fill(isCompleted ? Color.green : Color.blue)
            //누르고 있으면 너비가 늘어나게, 아니면 0으로 애니메이션을 통해 자연스럽게
                .frame(maxWidth: isPressed ? .infinity : 0)
                .frame(height: 55)
                .frame(maxWidth: .infinity, alignment: .leading)
                .background(Color.gray)
            
            VStack {
                Text("꾹 눌러요")
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.black)
                    .cornerRadius(10)
                
                //minimumDuration - 몇 초 동안 눌러야 하는가
                /*
                 maximumDistance - 누르고 나서(누른 상태를 유지한 채)
                 손가락을 화면의 다른 곳으로 이동해도 누르고 있다고
                 인정하는 범위(포인트 단위로)
                 */
                    .onLongPressGesture(minimumDuration: 2, maximumDistance: 100) {
                        //누르기가 끝났을 때 실행되는 코드(2초 후)
                        withAnimation(.easeInOut) {
                            isCompleted = true
                        }
                        //누르기 시작할 때 실행되는 코드
                        //isPressing은 Bool 타입
                    } onPressingChanged: { isPressing in
                        if isPressing {
                            withAnimation(.easeInOut(duration: 2.0)) {
                                isPressed = true
                            }
                        }
                        //만약 누르다가 손을 뗐을 때
                        else {
                            //정해진 시간만큼 다 눌렀는지 확인하고, 아니라면 누르고 있지 않다는 상태로 변경
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                                if !isCompleted {
                                    withAnimation(.easeOut) {
                                        isPressed = false
                                    }
                                }
                            }
                        }
                    }
                
                Text("리셋")
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.black)
                    .cornerRadius(10)
                    .onTapGesture {
                        isPressed = false
                        isCompleted = false
                    }
            }
        }
    }
}