티스토리 뷰

iOS

iOS ) Gesture Recognizer - Pinch

Zedd0202 2017. 12. 14. 19:07
반응형

안녕하세요 :) Zedd입니다.

Gesture Recognizer가 디게 많죠 

이많큼이나 있습니다.

스와이프와 탭빼고는 안써본거같아요..그래서 하나씩 써보기로 함

오늘은 Pinch를 사용해보겠습니다. 

그리고 이제부터 스토리보드로도 해보고, 코드로도 해볼려구요 :)


Gesture Recognizer - Pinch


역시 처음할때는 애플가이드를 봐야겠죠?

Handling Pinch Gestures를 참고할게요. 

먼저!! Pinch Gesture가 어떤건지 알아야겠죠?

이것이 바로 Pinch....바로 이해가죠?

애플의 Pinch에 대한 정확한 정의는 "두 손가락 사이 거리를 추적하고, 해당 정보를 사용하여 내용을 확대 또는 축소합니다."이에요.


그럼 프로젝트는 뭔가를 확대하고 축소하는....간단하게 이미지뷰를 확대하고 축소하는 걸로 결정!!!


프로젝트를 만들어주시고,

Pinch Gesture Recognizer를 추가해주세요 :) 일단 ImageView에 추가할 수도 있고, View에도 추가할 수 있을거에요. 일단 imageView로 줘봅시다.

그리고 IBoutlet을 따주세요 :) ImageView와 Pinch Gesture Recognizer!!


자..이제 해야할 걸 생각해봅시다.

이렇게 두 손가락을 쫙 벌렸다고 생각해볼게요. 

그럼 이 두손가락이 Pinch Gesture를 하고 있다고 감지해야겠죠?

그걸 간단하게 해주는 것이 Pinch Gesture Recognizer의 action입니다.

네!!! Pinch Gesture Recognizer에 IBAction이 존재한답니다. 

Pinch Gesture Recognizer말고도 Gesture Recognizer에는 다 IBAction이 있죠?

그럼 IBAction을 만들어줍시다.



그럼 이 IBAction안에 무슨 코드를 넣어야 할지 생각해봐야겠네요.

자..다시한번 생각해봅시다. 이제 내가 두 손가락으로 Pinch Gesture를 하면 무슨 행동을 해야할지요.

간단합니다. 내 이미지뷰가 확대되고 축소되면 되는거죠?

그럼 이 IBAction안에서 이미지뷰를 가지고 어케어케 해보면 될 것 같네요. 

친절하게도 애플문서에 나와있답니다. 


코드에 대한 이해가 쉽도록 Pinch Gesture에 대한 설명을 조금 더 볼게요.

Pinch Gesture Recognizer는 화면은 터치하는 두 손가락 사이의 거리 변화를 보고(report)합니다. Pinch Gesture는 연속적이므로 손가락 사이의 거리가 변경될 때마다 액션메소드가 호출됩니다. 손가락 사이의 거리는 scale factor로 보고됩니다. 제스쳐의 시작부분에서 scale factor는 1.0입니다. 두 손가락 거리가 증가함에 따라 scale factor가 비례하여 증가합니다. 유사하게, 손가락 사이의 거리가 감소함에 따라 scale factor는 감소합니다. 

Pinch Gesture는 화면에서 객체 또는 내용의 크기를 변경하는데 가장 일반적으로 사용됩니다. 예를들어, 지도View는 지도의 확대/축소 수준을 변경하기 위해 Pinch Gesture를 사용합니다.

Pinch Gesture Recognizer는 두 손가락 사이의 거리가 처음으로 변경된 후에만 begun state로 전환됩니다.

그 초기 변경후에, 거리에 대한 후속 변경은 Gesture Recognizer를 changed state로 두고, scale factor를 업데이트 합니다. 사용자의 손가락이 화면에서 들리면 Gesture Recognizer가 ended state가 됩니다. 


중요!!

Pinch Gesture Recognizer의 scale factor을 컨텐츠에 적용할 때 주의를 기울여야합니다.

그렇지 않으면 예기치 않은 결과가 발생할 수 있습니다.

action메소드가 여러번 호출될 수 있기 때문에(손가락 사이의 거리가 변경될 때마다 호출된다고 그랬죠?) 단순히 현재 scale factor를 컨텐츠에 적용할 수 없습니다.

이전에 action메소드를 호출하여 이미 조정된 컨텐츠의 현재값으로 각각의 새 스케일 값을 곱하면, 컨텐츠가 기하급수적으로 확대되거나 축소됩니다. 

대신 컨텐츠의 원래값을 저장하고, 원래값에 scale factor를 적용한 다음 새 값을 다시 컨텐츠에 적용하세요.

또는 각각의 새 변경사항을 적용한 후 scale factor를 1.0으로 재설정 하십시오.


마지막말이 핵심입니다. 이 scale factor를 1.0으로 다시 재설정하지 않으면 조금만 Pinch Gesture를 취해도 엄청나게 이미지가 확대되거나 축소됩니다. 

  1.  @IBAction func pinchAction(_ sender: Any) {

      myImageView.transform = myImageView.transform.scaledBy(x:                  pinchGestureRecognizer.scale, y: pinchGestureRecognizer.scale)

            pinchGestureRecognizer.scale = 1.0

      }

자꾸 위에서 뭘 곱하면,..이래가지고 뭘곱해;;;라고 생각하신분들도 계실거에요!

저도 궁금해서 찾아보니, scaledBy메소드가 곱셉으로 구현되는 것이었습니다!!

그러니까, scale factor는 1로 시작하여, 확대/축소를 하면 저 scale factor가 증가/감소가 되어 나중에는 기하급수적으로 확대/축소가 된다는 말이에요.

그러니까 우리는 이 action메소드가 불릴때 마다. 즉, 두 손가락의 거리가 변경됨에 따라 scale factor를 다시 1로 맞춰주자는 소리입니다.

그러면 기하급수적으로 늘어날일이 없으니까요.

이해가셨나요?


자, 이제 실행해봅시다.

혹시 아이폰이 아니신분들! 시뮬레이터로 돌리셔야할텐데 시뮬레이터에서 Pinch Gesture는 option키를 누르고 있으면 동그라미 두개가 나오게 되는데, 이걸로 Pinch Gesture를 할 수 있으니 참고하세요 :)

근데..아무리 imageView에다가 Pinch Gesture를 해도 안되네요..

왜이러지;;

친절하게 안될땐 이렇게 해봐~~~~라고 말해주는 애플찡

ImageView를 많이 다루시는분들은 눈치채셨을지도 모르지만, imageView는 기본적으로 isUserInteractionEnabled가 false로 세팅되어있습니다. 그래서 터치와 같은 상호작용이 먹지 않는 것이죠. 간단하게 코드로

  1. myImageView.isUserInteractionEnabled = true

를 해주시거나, 스토리보드에서 체크 해주세요.


그럼 이제 잘 되는 것을 볼 수 있습니다. 하지만, 


이렇게 이미지뷰 바깥에서 Pinch Gesture를 하면 확대/축소가 되지 않습니다.

이유는 Pinch Gesture Recognizer를 이미지뷰에 줬기 때문이에요!! 이 Pinch Gesture Recognizer를 전체 View에 주시면 imageView말고 View에 Pinch Gesture를 해도 확대/축소가 잘 될 거에요.

지금까지는 스토리보드를 이용한거였고, 코드로 해볼게여

  1. override func viewDidLoad() {

            super.viewDidLoad()


            let pinchRecogniezer = UIPinchGestureRecognizer(target: self, action: #selector(pinchAction(_ :)))

            myImageView.addGestureRecognizer(pinchRecogniezer)

        }

        @objc func  pinchAction(_ sender :UIPinchGestureRecognizer){

             myImageView.transform = myImageView.transform.scaledBy(x:                    sender.scale, y: sender.scale)

            sender.scale = 1.0

     }

이렇게 해주시면 된답니다. 

간단하네요 :) 

오늘도 도움이 되었길 바라며 ~.~


반응형