uinavigationController 를 사용하면 화면 왼쪽 끝부분에서 스와이프 할 때 popViewController 처럼 이전 화면으로 넘어갈 수 있지만,
화면 중앙이나 다른 부분에서는 스와이프를 해도 뒤로 넘어갈 수 없다.
화면 어디서나 swipe back 을 할 수 있도록 만드는 방법을 알아보았다.
카카오나 인스타그램의 경우 커스텀으로 swipe back 기능을 구현해주었는지,
화면 어디서나 스와이프를 하면 손 위치를 따라 뷰가 같이 움직이며 따라오지만
그것까지는 아니고, 그냥 어디서든 스와이프 하면 이전 화면으로 넘어갈 수 있도록만 구현하였다.
이거는 UISwipeGestureRecognizer 를 이용해서 간단하게 구현이 가능하다.
1. UISwipeGestureRecognizer
var swipeRecognizer: UISwipeGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
swipeRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(swipeAction(_:)))
swipeRecognizer.direction = .right
self.view.addGestureRecognizer(swipeRecognizer)
}
@objc func swipeAction(_ sender: UISwipeGestureRecognizer) {
if sender.direction == .right {
self.navigationController?.popViewController(animated: true)
}
}
2. RxGesture - swipe
RxGesture를 사용하면 gesture 인스턴스를 따로 생성해주지 않아도, 간단하게 rx로 처리가 가능하다.
self.view.rx.swipeGesture(.right)
.when(.recognized)
.bind { [weak self] _ in
self?.navigationController?.popViewController(animated: true)
}
.disposed(by: disposeBag)
swipe 제스처를 사용하면 스와이프가 잘 되기는 하는데, 제스처 감지가 너무 예민해서 살짝만 스쳐도 스와이프가 되어버리고
스와이프 제스처는 따로 제스처 감지 속도나 범위를 감지하고 커스텀으로 작동시키기가 힘들어서 UISwipeGestureRecognizer는 용도에 맞지 않는것 같아 PanGesture 를 이용하는 것으로 수정을 해보았다.
** 스와이프 제스처에도 state == .end 확인을 해줬으면 바로 넘어가진 않았으려나,, 추가로 테스트를 해봐야겠다.
-> 스와이프 제스처에는 state 로 상태관리 하는 기능은 지원되지 않는 것 같다.
자세한 것은 UISwipeGestureRecognize 를 이용한 스와이프 액션을 파헤쳐보자! 글을 참고해주세욥
2023-07-21
3. RxGesture - Pan
gpt 한테 물어봤더니 다음과 같이 pan gesture를 사용하는 방법을 알려주었다.
이렇게 하면 x 의 이동 범위와 pan 속도를 감지하여 원하는 값으로 pop view 를 구현해줄 수 있다.
그런데 위아래 스크롤인지 좌우 스와이프인지, 상하/좌우 이동을 감지하는 코드가 없어 위아래 스크롤을 할 때 오른쪽으로 살짝만 움직여도 스와이프가 되어버리는 치명적인 문제가 있었다.
gpt 아직 더 분발해 ~~
let translationX = gesture.translation(in: self.view).x
let velocityX = gesture.velocity(in: self.view).x
if gesture.state == .ended {
if translationX > 100 || velocityX > 300 {
self.navigationController?.popViewController(animated: true)
}
}
translation으로 x의 이동범위를 따로 구해주지 않아도,
gesture.velocity 의 magnitude 라는 절대값을 이용해 좌우 스크롤을 감지하고, 제스처 속도에 따라 액션을 설정해줄 수도 있다.
아래와 같이 설정해주니, 아아아주 잘 된다
self.view.rx.panGesture()
.when(.recognized)
.filter { [weak self] _ in self?.isInteractivePopGestureEnabled ?? true }
.bind { [weak self] gesture in
guard let self else { return }
let velocity = gesture.velocity(in: self.view)
if velocity.x.magnitude > velocity.y.magnitude { //좌우
if velocity.x > 0 {
if velocity.x.magnitude > 300 { //제스처 빠를 때
self.navigationController?.popViewController(animated: true)
} else { //제스처 느릴 때
}
}
}
}
.disposed(by: disposeBag)
굿굿! 👍🏻
+ 가로 스크롤 컬렉션 뷰 에서 오른쪽으로 스크롤하면 swipe back 되는 문제
Handling swipe gestures
'Swift iOS 앱 개발 > Swift' 카테고리의 다른 글
[Swift] UISwipeGestureRecognizer 를 이용한 스와이프 액션을 파헤쳐보자 ! (0) | 2023.07.28 |
---|---|
[Swift iOS] Lottie Animation 적용하기 (+ multiple animation) (0) | 2023.07.13 |
enum case 예외 처리 (default 값 설정) (0) | 2023.07.04 |
[Swift] Why double is preferred over float? (+ Int / Int32 / Int64) (0) | 2023.04.13 |
Swift 언어에 대하여 (0) | 2023.04.13 |