2016-07-29 3 views
1

나는 꼬집음 - 확대/축소 및 제스처 인식기를 집어 넣을 수있는 텍스트가 많은 레이블이 있습니다. 여기에서 조리법을 사용한 다음 각각을 중첩합니다 다른. 그것은 어디 (사진 아래에서 설명) 최상위 페이지 뷰 내에 정상 범위를의의Xamarin Pinch 경계를 벗어나는 컨테이너를 확대/축소하려면

https://developer.xamarin.com/guides/xamarin-forms/user-interface/gestures/pinch/

https://developer.xamarin.com/guides/xamarin-forms/user-interface/gestures/pan/

문제는, 두 컨테이너 개체는 완전히 외부 레이블을 이동할 수 있습니다.

여기에 몇 가지 제한을 구현하는 방법에 대한 의견이 있으십니까? 컨테이너 코드의 수학에 몇 가지 제한을 두는 것만 같지만 아직 바꿀 수있는 것을 찾지 못했습니다.

이러한 이미지에서 볼 수 있듯이 (병합하지 않은) 핀치 - 확대/축소 컨테이너와 확대/축소없는 팬 컨테이너는 모두 컨트롤을 변경하여 바운드 범위를 벗어나게합니다.

초기 레이아웃 :

Initial layout

핀치 - 투 - 줌 만

Pinch-To-Zoom only

Panning Only

핀치 및 P 패닝 ,

PinchToZoomContainer.cs

public class PinchToZoomContainer : ContentView 
{ 
    // Pinch Gesture variables 
    double currentScale = 1; 
    double startScale = 1; 
    double xOffset = 0; 
    double yOffset = 0; 


    public PinchToZoomContainer() 
    { 
     var pinchGesture = new PinchGestureRecognizer(); 
     pinchGesture.PinchUpdated += OnPinchUpdated; 
     GestureRecognizers.Add (pinchGesture); 

    } 



    void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e) 
    { 
     if (e.Status == GestureStatus.Started) { 
      // Store the current scale factor applied to the wrapped user interface element, 
      // and zero the components for the center point of the translate transform. 
      startScale = Content.Scale; 
      Content.AnchorX = 0; 
      Content.AnchorY = 0; 
     } 
     if (e.Status == GestureStatus.Running) { 
      // Calculate the scale factor to be applied. 
      currentScale += (e.Scale - 1) * startScale; 
      currentScale = Math.Max (1, currentScale); 

      // The ScaleOrigin is in relative coordinates to the wrapped user interface element, 
      // so get the X pixel coordinate. 
      double renderedX = Content.X + xOffset; 
      double deltaX = renderedX/Width; 
      double deltaWidth = Width/(Content.Width * startScale); 
      double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth; 

      // The ScaleOrigin is in relative coordinates to the wrapped user interface element, 
      // so get the Y pixel coordinate. 
      double renderedY = Content.Y + yOffset; 
      double deltaY = renderedY/Height; 
      double deltaHeight = Height/(Content.Height * startScale); 
      double originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight; 

      // Calculate the transformed element pixel coordinates. 
      double targetX = xOffset - (originX * Content.Width) * (currentScale - startScale); 
      double targetY = yOffset - (originY * Content.Height) * (currentScale - startScale); 

      // Apply translation based on the change in origin. 
      Content.TranslationX = targetX.Clamp (-Content.Width * (currentScale - 1), 0); 
      Content.TranslationY = targetY.Clamp (-Content.Height * (currentScale - 1), 0); 

      // Apply scale factor 
      Content.Scale = currentScale; 
     } 
     if (e.Status == GestureStatus.Completed) { 
      // Store the translation delta's of the wrapped user interface element. 
      xOffset = Content.TranslationX; 
      yOffset = Content.TranslationY; 
     } 
    } 

PanContainer.cs

내가 상상
public class PanContainer : ContentView 
{ 
    double startX, startY; 
    double x, y; 

    public PanContainer() 
    { 
     // Set PanGestureRecognizer.TouchPoints to control the 
     // number of touch points needed to pan 
     var panGesture = new PanGestureRecognizer(); 
     panGesture.PanUpdated += OnPanUpdated; 
     GestureRecognizers.Add (panGesture); 
    } 

    void OnPanUpdated (object sender, PanUpdatedEventArgs e) 
    { 
     switch (e.StatusType) { 

     case GestureStatus.Started: 
      startX = Content.TranslationX; 
      startY = Content.TranslationY; 
      break; 


     case GestureStatus.Running: 

      // Translate and ensure we don't pan beyond the wrapped user interface element bounds. 
      //Content.TranslationX = Math.Max (Math.Min (0, x + e.TotalX), -Math.Abs (Content.Width - App.ScreenWidth));// App.ScreenWidth)); 
      //Content.TranslationY = Math.Max (Math.Min (0, y + e.TotalY), -Math.Abs (Content.Height - App.ScreenHeight)); //App.ScreenHeight));  
      Content.TranslationX = startX + e.TotalX; 
      Content.TranslationY = startY + e.TotalY; 

      break; 

     case GestureStatus.Completed: 
      // Store the translation applied during the pan 
      x = Content.TranslationX; 
      y = Content.TranslationY; 
      break; 
     } 
    } 
} 

:

Pinch and Pan

링크는 위의 컨테이너 코드를 가지고 있지만, 여기있다 PanContainer에서 내 문제는이 줄에 내가 ut :

  //Content.TranslationX = Math.Max (Math.Min (0, x + e.TotalX), -Math.Abs (Content.Width - App.ScreenWidth));// App.ScreenWidth)); 
      //Content.TranslationY = Math.Max (Math.Min (0, y + e.TotalY), -Math.Abs (Content.Height - App.ScreenHeight)); //App.ScreenHeight));  

App.ScreenWidth 또는 .ScreenHeight 속성을 찾을 수 없어 좀 더 간단한 버전으로 변경했습니다.

그러나 핀치 컨테이너는 원래 제조법과 동일하지만 여전히 범위를 벗어납니다.

답변

0

이 답변은 대부분 사용자의 요구에 매우 늦을 가능성이 있지만 Chet ... 그러나 ScrollView에서 모든 것을 랩핑 할 수 있습니다 (필요에 따라 적절히 배치하거나 크기를 정할 수 있음). 예상대로 작동합니다.

<ScrollView Grid.Column="2" VerticalOptions="Start"> 
    <PanContainer> 
     <PanContainer.Content> 
     <Image x:Name="SomeImage" Aspect="AspectFit" /> 
     </PanContainer.Content> 
    </PanContainer> 
    </ScrollView> 

건배! 마이크

+0

아니요, 괜찮습니다. Stack Exchange는 답이 괜찮 으면 오래된 질문에 새로운 답을 올리더라도 상관하지 않습니다. –

+0

고마워요,하지만 스크롤 할뿐만 아니라 확대 할 수 있어야했습니다. 나는 내 목표를 달성하기 위해 다른 길로 나아 갔다. 그러나 그 아이디어에 대해 감사한다. –

0

이 문제와 관련하여 도움이 된 IsClippedToBounds 속성이 있습니다.예를 들어

가 :

<PanContainer IsClippedToBounds="true"> 
    <PanContainer.Content> 
     <Image x:Name="SomeImage" /> 
    </PanContainer.Content> 
</PanContainer> 

핀치와 팬을 얻으려면, 당신은 팬 요소 또는 그 반대의 핀치 요소를 포장 할 수 있습니다, 또는 둘 다 핀치에서 기능을 하나의 클래스를 만들 수 있으며, 팬 클래스. 아마 후자가 더 좋다.

pinch 및 pan 기능의 계산이 서로를 인식하지 못하기 때문에 예상대로 작동하지 않을 수 있습니다. 예를 들어 확대/축소 기능을 집어 넣으면 팬 기능이이를 알지 못합니다. 이제 더 멀리 이동할 수 있습니다.

관련 문제