Handling Pinch Gestures

Panther·2021년 7월 30일
0

https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_uikit_gestures/handling_pinch_gestures

"Track the distance between two fingers and use that information to scale or zoom your content."

두 손가락 사이의 간격을 추적하고, 이 정보를 컨텐트 스케일 혹은 확대에 사용합니다.

Overview

핀치 제스쳐는 스크린을 터치하는 처음 두 손가락 사이의 거리를 추적하는 연속적 제스쳐입니다. 핀치 제스쳐를 감지하려면 UIPinchGestureRecognizer 클래스를 사용해야 합니다.

제스쳐 리코그나이저의 구현은 아래 방법 중 한 가지로 할 수 있습니다.

  • 코드 작성으로 구현하는 방법입니다. 뷰의 addGestureRecognizer(_:) 메소드를 호출합니다.
  • 인터페이스 빌더에서 구현하는 방법입니다. 라이브러리로부터 적합한 객체를 드래그하고 뷰에 드롭합니다.

핀치 제스쳐는 스크린을 터치하고 있는 두 손가락 사이의 간격에게 변경사항을 알려줍니다. 핀치 제스쳐는 연속적이기 때문에 손가락 사이의 간격이 바뀔 때마다 액션 메소드가 호출됩니다. 손가락 사이의 간격은 스케일 요소로써 알려집니다. 제스쳐의 시작 시점에 스케일 팩터는 1.0입니다. 두 손가락 사이의 간격이 늘어날 때, 스케일 요소는 비율로 비례해 중가합니다. 유사하게 손가락 사이 간격이 줄어들면, 스케일 요소 역시 감소합니다. 핀치 제스쳐는 주로 화면에 나타나는 객체 혹은 컨텐트의 크기를 변경시키려는 목적으로 사용됩니다. 예를 들어 지도 뷰는 맵의 확대 수준을 변경시키기 위해 핀치 제스쳐를 사용합니다.

핀치 제스쳐 리코그나이저는 두 손가락 사이 거리가 처음으로 변경될 때에만 UIGestureRecognizer.State.began 상태에 진입합니다. 이와 같은 초기 변경사항 이후 간격에 대한 후속 변경은 제스쳐 리코그나이저의 상태를 UIGestureRecognizer.State.changed로 두고 스케일 요소를 업데이트 합니다. 사용자의 손가락이 스크린으로부터 빠져나오면, 제스쳐 리코그나이져는 UIGestureRecognizer.State.ended에 진입합니다.

Important
컨텐트에 핀치 제스쳐 리코그나이저의 스케일 요소를 적용할 때 주의를 기울이지 않으면 예상하지 않은 결과를 가져올 수도 있습니다. 액션 메소드는 여러번 호출되기 때문에 컨텐트에 단순히 현재 스케일 요소를 적용할 수 없습니다. 만약 이전에 액션 메소드 호출을 통해 스케일된 컨텐트의 현재 값으로 각각의 새 스케일 값을 곱하면, 컨텐트는 기하급수적으로 커지거나 줄어듭니다. 대신 컨텐트의 기존 값을 캐시하고, 해당 기존 값에 스케일 요소를 적용해야 합니다. 그리고 컨텐트에 다시 새 값을 적용해야 합니다. 다른 방법으로 각 변경사항이 적용된 이후 스케일 요소를 1.0으로 재설정하는 것이 있습니다.

Listing 1은 핀치 제스쳐 리코그나이저를 사용해 선형적으로 뷰의 크기를 재조절하는 방법을 설명합니다. 이 액션 메소드는 뷰의 변형에 현재 스케일 요소를 적용하고, 이후 제스쳐 리코그나이저의 스케일 속성을 1.0으로 재설정합니다. 스케일 요소를 재설정하는 것은 값이 재설정된 이후 제스쳐 리코그나이저가 오직 변경의 크기만을 알리도록 합니다. 이는 뷰의 선형적 스케일링만을 초래하는 경우입니다.

Listing 1 Scaling a view

@IBAction func scalePiece(_ gestureRecognizer : UIPinchGestureRecognizer) {   guard gestureRecognizer.view != nil else { return }

   if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
      gestureRecognizer.view?.transform = (gestureRecognizer.view?.transform.
                    scaledBy(x: gestureRecognizer.scale, y: gestureRecognizer.scale))!
      gestureRecognizer.scale = 1.0
   }}

만약 핀치 제스쳐 리코그나이저를 위한 코드가 호출되지 않거나 정확하게 작동하지 않는다면, 아래 조건이 true인지 확인하고 필요한 경우 수정하시기 바랍니다.

  • 뷰의 isUserInteractionEnabled 속성이 true로 설정되어 있는지 확인합니다. 이미지 뷰와 레이블은 이 속성이 기본값으로 false입니다.
  • 적어도 두 손가락이 스크린을 터치하고 있는지 확인합니다.
  • 컨텐트에 정확하게 스케일 요소를 적용하고 있는지 확인합니다. 값의 기하급수적 증가는 현재 값에 스케일 요소를 단순하게 적용할 경우 발생합니다.

0개의 댓글