2019년 9월 22일 일요일

아래로 당겨서 뷰 내리기 (Pull Down to Dismiss View)



상황
  • 테이블뷰나 웹뷰처럼 스크롤뷰가 작동하는 경우 아래로 당겨서 뷰를 해제하려고 함 (테이블 뷰는 스크롤뷰를 상속받았고, WKWebView는 scrollView가 프로퍼티로 존재함) 
방법 
  • UIPanGestureRecognizer를 이용함 
  • 중복되는 제스처를 처리하기 위해 UIGestureRecognizerDelegate를 채택 후 위임
내용


var isTrackingPanLocation = false
func setPanGesture() {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(closePopUpViewWithPanGesture(_:)))
tableView.addGestureRecognizer(panGesture)
panGesture.minimumNumberOfTouches = 1
panGesture.maximumNumberOfTouches = 1
panGesture.delegate = self
}
@objc func closePopUpViewWithPanGesture(_ sender: UIPanGestureRecognizer) {
if sender.state == .began {
print("bb")
sender.setTranslation(CGPoint.zero, in: tableView)
isTrackingPanLocation = true
} else if sender.state != .ended && sender.state != .cancelled && sender.state != .failed && isTrackingPanLocation {
let panOffset = sender.translation(in: tableView)
let eligiblePanOffset = panOffset.y > 200
if eligiblePanOffset {
sender.isEnabled = false
sender.isEnabled = true
UIView.animate(withDuration: 0.6) {
self.popUpConstraint.constant = 1200
self.view.layoutIfNeeded()
}
}
if panOffset.y < 0 {
isTrackingPanLocation = false
}
} else {
isTrackingPanLocation = false
}
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
추가확인사항 
  • sender.isEnabled = false , sender.isEnabled = true 이처럼 불리언 값을 한번 변경해주지 않으면 해당 위치에 로그가 연속적으로 찍힘
  • 웹뷰일 때는 웹뷰의 스크롤뷰 프로퍼티로 접근함 if recognizer.state == .began && webView.scrollView.contentOffset.y == 0 { (…)} 
  • 뷰가 사라지는 시점이 터치를 끝낸 시점이 아니라 애니메이션 효과가 도중에 발생함 
참고: 1