2011-11-02 1 views
1

UIPinchGestureRecognizer 및 UIPanGestureRecognizer를 imageView에 첨부하여 드래그하여 크기를 조정할 수있는 간단한 앱이 있습니다. 이미지 뷰를 부분적으로 화면에서 벗어나 디스플레이에서 최소화 할 수 있도록 이미지의 작은 75 픽셀 부분이 디스플레이에 남아 있도록 이미지를 다시 끌어다 놓을 수 있도록 만들었습니다. 예를 들어 이미지 뷰를 디스플레이의 오른쪽 부분에서 드래그하려고하면 이미지 뷰의 75 픽셀이 남아있을 때 이미지 뷰가 멈추고 이미지 뷰를 드래그 할만큼 충분한 공간이 남습니다. 스케일링과 같은 개념으로, 내가 만드는 경계 프레임은 이미지 뷰가 디스플레이에서 최소화되는 것을 방지합니다.이미지가 너무 크게 확대되면 UIPinchGestureRecognizer가 재미있어 함

아무튼, 나는 UIPinchGestureRecognizer 대리자 메서드에서 내 경계 코드에이 문제를 겪고 있습니다. 내가 경계를하고있는 방식은 imageViews 수퍼 뷰의 복제본 인 프레임을 만드는 것입니다. 단, 각면과 위쪽과 아래쪽의 75 픽셀로 푸시됩니다. imageView가이 프레임과 교차하지 않는지 확인한 다음 오른쪽/왼쪽 또는 위쪽/아래쪽 경계 중 하나에 도달했는지 확인합니다. 대부분의 경우 효과적이지만, 이미지가 상당히 커지면 (일반적으로 1000 x 1000 이상), 경계가 작동하지 않습니다. - 내가 극도로 빠른 최소화 스케일을 수행하면 imageView가 화면에서 완전히 푸시됩니다 그래서 다시 끌 수는 없습니다.

왜 이런 일이 발생하는지 궁금합니다. 이미지 크기가 너무 커지면 어떻게해야합니까? 아니면 내 코드의 결함입니까? (나는 아래에 열거했다). 누구든지 도움을받을 수 있다면 감사하겠습니다.

- (void)scale:(UIPinchGestureRecognizer *)sender 
{ 
    if([sender state] == UIGestureRecognizerStateBegan) 
    { 
     lastScale = [sender scale]; 
    } 

    if ([sender state] == UIGestureRecognizerStateBegan || 
     [sender state] == UIGestureRecognizerStateChanged) 
    { 
     CGFloat currentScale = [[[sender view].layer valueForKeyPath:@"transform.scale"] floatValue]; 
     CGFloat newScale = 1 - (lastScale - [sender scale]);// * (CropThePhotoViewControllerPinchSpeed);  
     newScale = MAX(newScale, CropThePhotoViewControllerMinScale/currentScale); 

     CGFloat scaledWidth = newScale * sender.view.frame.size.width; 
     CGFloat scaledHeight = newScale * sender.view.frame.size.height; 

     CGRect translatedRect = CGRectMake(sender.view.frame.origin.x, sender.view.frame.origin.y, scaledWidth, scaledHeight); 
     CGRect boundaryRect = CGRectMake(sender.view.superview.frame.origin.x + CropThePhotoViewControllerBoundaryBuffer, sender.view.superview.frame.origin.y + CropThePhotoViewControllerBoundaryBuffer, sender.view.superview.frame.size.width - (CropThePhotoViewControllerBoundaryBuffer * 2), sender.view.superview.frame.size.height - (CropThePhotoViewControllerBoundaryBuffer * 2)); 

     if (!(!CGRectIntersectsRect(boundaryRect,translatedRect) && newScale < 1)) 
     { 
      CGAffineTransform transform = CGAffineTransformScale([[sender view] transform], newScale, newScale); 
      [[sender view] setTransform: transform]; 
      lastScale = [sender scale];; 
     } 
    } 
} 

답변

1

무엇이 잘못되었는지 알아 냈습니다. 이 코드 줄, 나는 잘못 x와 y 값을 설정했다 :

CGRect translatedRect = CGRectMake(sender.view.frame.origin.x, sender.view.frame.origin.y, scaledWidth, scaledHeight); 

그것은해야한다 : 나는 기원이 때 이동 거라는 사실을 차지하지 않은

CGRect translatedRect = CGRectMake(sender.view.frame.origin.x + (((sender.view.frame.size.width - scaledWidth)/2)), sender.view.frame.origin.y + (((sender.view.frame.size.height - scaledHeight)/2)), scaledWidth, scaledHeight); 

이미지 뷰가 축소되었습니다.

이 변경 사항을 적용하고 실제로 개선 할 방법을 업데이트했습니다. 이제 사용자가 경계를 넘어서 최소화하려는 경우 대신에 스케일을 수행하지 않고 대신 imageView를 테두리로 이동합니다. 이것은 더 부드럽고 궁극적으로 더 좋습니다. 테스트가 끝난 후에도 잘 작동하지만 아무도 버그를 발견하면 알려 주시기 바랍니다.

- (void)scale:(UIPinchGestureRecognizer *)sender 
{ 
    if([sender state] == UIGestureRecognizerStateBegan) 
    { 
     previousScale = [sender scale]; 
    } 


    if ([sender state] == UIGestureRecognizerStateBegan || 
     [sender state] == UIGestureRecognizerStateChanged) 
    { 
     CGFloat nextScale = 1 - (previousScale - [sender scale]);// * (CropThePhotoViewControllerPinchSpeed); 

     nextScale = MAX(nextScale, CropThePhotoViewControllerMinScale/[[[sender view].layer valueForKeyPath:@"transform.scale"] floatValue]); 

     CGFloat scaledWidth = nextScale * sender.view.frame.size.width; 
     CGFloat scaledHeight = nextScale * sender.view.frame.size.height; 
     CGFloat currentScale = [sender scale]; 

     CGRect translatedRect = CGRectMake(sender.view.frame.origin.x + (((sender.view.frame.size.width - scaledWidth)/2)), sender.view.frame.origin.y + (((sender.view.frame.size.height - scaledHeight)/2)), scaledWidth, scaledHeight); 
     CGRect boundaryRect = CGRectMake(sender.view.superview.frame.origin.x + CropThePhotoViewControllerBoundaryBuffer, sender.view.superview.frame.origin.y + CropThePhotoViewControllerBoundaryBuffer, sender.view.superview.frame.size.width - (CropThePhotoViewControllerBoundaryBuffer * 2), sender.view.superview.frame.size.height - (CropThePhotoViewControllerBoundaryBuffer * 2)); 

     if ((!CGRectIntersectsRect(boundaryRect,translatedRect)) && (nextScale < 1))   
     { 
      CGFloat leftScaledEdge, rightScaledEdge, topScaledEdge, bottomScaledEdge; 
      CGFloat leftBoundary, rightBoundary, topBoundary, bottomBoundary; 
      CGFloat nextXScale, nextYScale; 

      nextXScale = CGFLOAT_MIN; 
      nextYScale = CGFLOAT_MIN; 

      rightScaledEdge = translatedRect.origin.x + translatedRect.size.width; 
      leftScaledEdge = translatedRect.origin.x; 
      bottomScaledEdge = translatedRect.origin.y + translatedRect.size.height; 
      topScaledEdge = translatedRect.origin.y; 

      leftBoundary = boundaryRect.origin.x; 
      rightBoundary = boundaryRect.origin.x + boundaryRect.size.width; 
      topBoundary = boundaryRect.origin.y; 
      bottomBoundary = boundaryRect.origin.y + boundaryRect.size.height; 

      if (rightScaledEdge < leftBoundary || leftScaledEdge > rightBoundary) 
      { 
       if (rightScaledEdge < leftBoundary) 
       { 
        CGFloat adjustedWidth = sender.view.frame.size.width - fabsf((leftBoundary - (sender.view.frame.origin.x + sender.view.frame.size.width))); 
        nextXScale = (nextScale * (adjustedWidth))/scaledWidth; 
       } 
       else 
       { 
        CGFloat adjustedWidth = sender.view.frame.size.width - fabsf((rightBoundary - sender.view.frame.origin.x)); 
        nextXScale = (nextScale * (adjustedWidth))/scaledWidth; 
       } 
      } 

      if (bottomScaledEdge < topBoundary || topScaledEdge > bottomBoundary) 
      { 
       if (bottomScaledEdge < topBoundary) 
       { 
        CGFloat adjustedHeight = sender.view.frame.size.height - fabsf((topBoundary - (sender.view.frame.origin.y + sender.view.frame.size.height))); 
        nextYScale = (nextScale * (adjustedHeight))/scaledHeight; 
       } 
       else 
       { 
        CGFloat adjustedHeight = sender.view.frame.size.height - fabsf((bottomBoundary - sender.view.frame.origin.y)); 
        nextYScale = (nextScale * (adjustedHeight))/scaledHeight; 

       } 
      } 

      if (nextXScale >= nextYScale) 
      { 
       nextScale = nextXScale; 
      } 
      else 
      { 
       nextScale = nextYScale; 
      } 

      currentScale = nextScale - 1 + previousScale; 
     } 

     CGAffineTransform transform = CGAffineTransformScale([[sender view] transform], nextScale, nextScale); 
     [[sender view] setTransform: transform]; 
     previousScale = currentScale; 
    } 
1

스케일링 결과를 NaN (숫자가 아님)으로 확인한 다음 개별적으로 처리해야한다는 것을 알고 있습니다. 확인하려면 isnan()을 사용하십시오.

+0

감사합니다. 나는 NaNs를 찾다가 아무 것도 나타나지 않았다. 내 문제는 그밖에 어디에서, 나는 그것에 대해 내 대답에서 썼다. –

관련 문제