2016-07-29 11 views
1

Ich habe ein Etikett mit viel Text, die Pinch-to-Zoom und Panning Gestenerkennung aktivieren möchten. Ich habe die Rezepte von hier und dann verschachtelt sie in jedem andere.Xamarin Prise zum Zoomen und Pan Container verlassen ihre Grenzen

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

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

Problem ist, erlauben die beiden Containerobjekte Sie das Etikett vollständig außerhalb zu bewegen es in der Top-Level-Seite Ansicht überall normalen Grenzen ist (in den Bildern unten gezeigt).

Irgendwelche Gedanken darüber, wie man einige Grenzen bei diesen implementiert? Ich bin mir sicher, dass es nur einige Einschränkungen für die Mathematik im Container-Code gibt, aber ich habe noch nicht das Richtige gefunden, um es zu ändern.

Wie Sie in diesen Bildern sehen können, können Sie mit dem Pinch-to-Zoom-Container (ohne Panning) und dem Pan-Container (ohne Zoomen) das Steuerelement so ändern, dass es seine Grenzen überschreitet.

Initial Layout:

Initial layout

Pinch-To-Zoom nur

Pinch-To-Zoom only

Schwenk nur

Panning Only

Pinch und P ein

Pinch and Pan

Die Links haben über den Container-Code, aber hier ist es:

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; 
     } 
    } 
} 

Ich stelle mir vor, Auf dem PanContainer ist mein Problem in diesen Zeilen, die ich kommentieren musste 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));  

Ich änderte diese eine einfachere Version, weil ich App.ScreenWidth oder .ScreenHeight nicht Eigenschaften finden.

Der Pinch Container ist jedoch genau so, wie er ursprünglich im Rezept war und geht immer noch außerhalb der Grenzen.

Antwort

0

Diese Antwort ist meistens sehr spät für Ihre Bedürfnisse, Chet ... aber Sie können das Ganze einfach in eine ScrollView einpacken (die Sie entsprechend finden und/oder an Ihre Bedürfnisse anpassen können). Das sollte wie erwartet funktionieren.

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

Prost! Mike

+0

Nein, es ist in Ordnung. Stack Exchange ist es egal, ob Sie eine neue Antwort auf eine alte Frage veröffentlichen, solange Ihre Antwort anständig ist. –

+0

Danke, aber ich musste in der Lage sein zu vergrößern, nicht nur scrollen. Ich habe einen anderen Weg eingeschlagen, um mein Ziel zu erreichen, aber danke für die Idee. –

0

Es gibt eine IsClippedToBounds Eigenschaft, die mir bei diesem Problem geholfen hat.

Zum Beispiel:

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

Um Prise und Pfanne, können Sie entweder wickeln Sie ein Klemmelement in einer Pfanne Element oder umgekehrt, oder Sie können eine einzige Klasse mit den Funktionen sowohl von der Pinch erstellen und Pan Klassen. Letzteres ist wahrscheinlich besser.

Das allein wird wahrscheinlich nicht genau so funktionieren, wie Sie es erwarten, weil die Berechnungen in der Pinch- und Pan-Funktionalität sich gegenseitig nicht kennen, also wenn Sie zum Vergrößern zoomen, dann weiß die Pan-Funktionalität das nicht kann jetzt weiter schwenken.