32YB SOPT/APPJAM - PPPClub

[Swift] UIPanGestureRecognizer 에서 touch(.changed) 중에 뷰 넘어가도록(.end 실행) 코드 수정

신_이나 2023. 7. 20. 18:56

 

 

 

메인 뷰를 맡으면서 가장 마음에 크게 쓰이는 오류가 있었다. 

우선 내가 구현한 보라색 티켓 커버를 잡고 아래로 끈 뒤 일정 위치에서 손을 떼면 티켓 커버가 아래로 떨어지면서 다음 뷰로 넘어가는 애니메이션이다. 하지만 큰 문제(?)가 있었는데 ,,,

 

 

 

 

 

 

 

위는 시뮬레이션 영상이다. 중간에 바로 넘어가지 않은 이유가 티켓을 잡아끌 때 손을 떼지 않아서다.

만약 유저가 티켓을 잡아끄는데 손을 떼지 않는다면? 손을 뗄 때 까지 영원히 넘어가지 않는다 ,,,

 

 

 

우선 코드는

@objc
    private func ticketCaseMoved(_ sender: UIPanGestureRecognizer) {
        
        viewTranslation = sender.translation(in: rootView.homeWeeklyView.ticketCoverImageView)
        viewVelocity = sender.velocity(in: rootView.homeWeeklyView.ticketCoverImageView)
        
        switch sender.state {
        case .changed:
            if abs(viewVelocity.y) > abs(viewVelocity.x) {
                
                if viewTranslation.y >= 152 {
                    UIView.animate(withDuration: 0.4, animations: {
                        self.rootView.homeWeeklyView.ticketCoverImageView.transform = CGAffineTransform(translationX: 0, y: 600)
                    })
                }
                
                else if viewVelocity.y > 0 {
                    UIView.animate(withDuration: 0.1, animations: {
                        self.rootView.homeWeeklyView.ticketCoverImageView.transform = CGAffineTransform(translationX: 0, y: self.viewTranslation.y)
                    })
                }
            }
            
        case .ended:
            if viewTranslation.y < 152 {
                UIView.animate(withDuration: 0.04, animations: {
                    self.rootView.homeWeeklyView.ticketCoverImageView.transform = .identity
                })
            }
            else {
                self.ticketDragAnimation()
            }
            
        default:
            break
            
        }
    }

 

 

 

1. changed 에서 animateKeyframes 을 사용하여 뷰가 내려가는 애니메이션 후, ticketDragAnimation() 이 구현되도록 하였다.

=> 실패

2. animate 내부에서 delay 를 주었다.

=> 실패

3. 애니메이션이 끝나고.ended 를 주어서 강제로 끝나게 하였다.

=> 실패

4. ,,,, 등등등

 

 

 

이틀 정도 온갖 방법을 쓰다가 결국 실패하였다. 그러다 데모데이 이틀 전에 우리의 멘토인 한솔 오빠에게 질문하였더니 sender.state = ended 라는 소중한 방법을 알려주셨다.

 결국 구현한 방법은

 

 

 

//.changed 내부 함수

if viewTranslation.y >= 152 {
                    UIView.animate(withDuration: 0.1, animations: {
                        self.rootView.homeWeeklyView.ticketCoverImageView.transform = CGAffineTransform(translationX: 0, y: 600)
                        sender.state = .ended
                    }, completion: { _ in
                        self.ticketDragAnimation()
                    })
                }

 

 

ended 를 불러온 뒤, copletion 에서 draganimation 을 구현하는 것이다.

그리고 돌려보면 ,,,,

 

 

 

 

 

 

아무리 잡고 있어도,, 애니메이션이 잘 구현되고, 티켓이 아래로 떨어진 뒤 뷰가 넘어간다 ,,, 진짜 소중하다.

 

 

 

아래는 전체코드

@objc
    private func ticketCaseMoved(_ sender: UIPanGestureRecognizer) {
        
        viewTranslation = sender.translation(in: rootView.homeWeeklyView.ticketCoverImageView)
        viewVelocity = sender.velocity(in: rootView.homeWeeklyView.ticketCoverImageView)
        
        switch sender.state {
        case .changed:
            if abs(viewVelocity.y) > abs(viewVelocity.x) {
                
                if viewTranslation.y >= 152 {
                    UIView.animate(withDuration: 0.1, animations: {
                        self.rootView.homeWeeklyView.ticketCoverImageView.transform = CGAffineTransform(translationX: 0, y: 600)
                        sender.state = .ended
                    }, completion: { _ in
                        self.ticketDragAnimation()
                    })
                }
                
                else if viewVelocity.y > 0 {
                    UIView.animate(withDuration: 0.1, animations: {
                        self.rootView.homeWeeklyView.ticketCoverImageView.transform = CGAffineTransform(translationX: 0, y: self.viewTranslation.y)
                    })
                }
            }
            
        case .ended:
            if viewTranslation.y < 152 {
                UIView.animate(withDuration: 0.04, animations: {
                    self.rootView.homeWeeklyView.ticketCoverImageView.transform = .identity
                })
            }
            
        default:
            break
            
        }
    }

 

 

 

 

사실 내가 제일 재밌게 생각했던, 그리고 첫 화면이라 소중하게 생각했던 애니메이션인데 이렇게 어떻게든지 완성시켜서 너무 기분이 좋다. 사실 울었다 하하 아무래도 나 개발 해야겠다,,, 어쩔 수가 없겠다.