Aggiungere un riconoscitore movimento panoramica

Download Sample Scaricare l'esempio

Il movimento di panoramica viene usato per rilevare il movimento delle dita sullo schermo e applicare tale movimento al contenuto e viene implementato con la classe PanGestureRecognizer. Uno scenario comune per questo movimento è l'esecuzione di una panoramica in orizzontale e in verticale di un'immagine, in modo da poter vedere tutto il contenuto dell'immagine quando è visualizzata in un viewport più piccolo rispetto alle dimensioni dell'immagine. Questa operazione viene eseguita spostando l'immagine all'interno del viewport ed è illustrata in questo articolo.

Per supportare lo spostamento di un elemento dell'interfaccia utente tramite il movimento di panoramica, creare un'istanza di PanGestureRecognizer, gestire l'evento PanUpdated e aggiungere il nuovo sistema di riconoscimento dei movimenti alla raccolta GestureRecognizers nell'elemento dell'interfaccia utente. L'esempio di codice seguente visualizza un PanGestureRecognizer associato a un elemento Image:

var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += (s, e) => {
  // Handle the pan
};
image.GestureRecognizers.Add(panGesture);

Questo risultato può essere ottenuto anche in XAML, come illustrato nell'esempio di codice seguente:

<Image Source="MonoMonkey.jpg">
  <Image.GestureRecognizers>
    <PanGestureRecognizer PanUpdated="OnPanUpdated" />
  </Image.GestureRecognizers>
</Image>

Il codice del gestore eventi OnPanUpdated viene quindi aggiunto al file code-behind:

void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
  // Handle the pan
}

Creazione di un contenitore di panoramica

Questa sezione contiene una classe helper generalizzata che consente di eseguire la panoramica a mano libera, adatta in genere agli spostamenti all'interno di immagini o mappe. La gestione del movimento di panoramica per eseguire questa operazione richiede alcuni calcoli matematici per la trasformazione dell'interfaccia utente. Questi calcoli matematici vengono usati per eseguire la panoramica solo entro i limiti dell'elemento di interfaccia utente sottoposto a wrapping. L'esempio di codice seguente visualizza la classe PanContainer:

public class PanContainer : ContentView
{
  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)
  {
    ...
  }
}

È possibile eseguire il wrapping di questa classe per un elemento dell'interfaccia utente, in modo che il movimento esegua la panoramica dell'elemento dell'interfaccia utente sottoposto a wrapping. L'esempio di codice XAML seguente visualizza il wrapping PanContainer di un elemento Image:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:PanGesture"
             x:Class="PanGesture.HomePage">
    <ContentPage.Content>
        <AbsoluteLayout>
            <local:PanContainer>
                <Image Source="MonoMonkey.jpg" WidthRequest="1024" HeightRequest="768" />
            </local:PanContainer>
        </AbsoluteLayout>
    </ContentPage.Content>
</ContentPage>

L'esempio di codice seguente illustra come PanContainer esegue il wrapping di un elemento Image in una pagina C#:

public class HomePageCS : ContentPage
{
  public HomePageCS ()
  {
    Content = new AbsoluteLayout {
      Padding = new Thickness (20),
      Children = {
        new PanContainer {
          Content = new Image {
            Source = ImageSource.FromFile ("MonoMonkey.jpg"),
            WidthRequest = 1024,
            HeightRequest = 768
          }
        }
      }
    };
  }
}

In entrambi gli esempi, le proprietà WidthRequest e HeightRequest vengono impostate sui valori di larghezza e altezza dell'immagine visualizzata.

Quando l'elemento Image riceve un movimento di panoramica, verrà eseguita la panoramica dell'immagine visualizzata. La panoramica viene eseguita dal metodo PanContainer.OnPanUpdated, visualizzato nell'esempio di codice seguente:

void OnPanUpdated (object sender, PanUpdatedEventArgs e)
{
  switch (e.StatusType) {
  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));
    Content.TranslationY =
      Math.Max (Math.Min (0, y + e.TotalY), -Math.Abs (Content.Height - App.ScreenHeight));
    break;

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

Questo metodo aggiorna il contenuto visualizzabile dell'elemento dell'interfaccia utente sottoposto a wrapping in base al movimento di panoramica dell'utente. Questo avviene usando i valori delle proprietà TotalX e TotalY dell'istanza di PanUpdatedEventArgs per calcolare la direzione e la distanza della panoramica. Le proprietà App.ScreenWidth e App.ScreenHeight specificano l'altezza e la larghezza del viewport e vengono impostate sui valori di larghezza e altezza dello schermo del dispositivo dai rispettivi progetti specifici della piattaforma. Viene quindi eseguita la panoramica dell'elemento dell'interfaccia utente sottoposto a wrapping impostandone le proprietà TranslationX e TranslationY sui valori calcolati.

Per la panoramica del contenuto in un elemento che non occupa l'intero schermo, l'altezza e la larghezza del viewport possono essere ottenuti dalle proprietà Height e Width dell'elemento.

Nota

La visualizzazione di immagini ad alta risoluzione può aumentare notevolmente il footprint della memoria dell'app. Di conseguenza, tali risorse devono essere create solo se necessario e rilasciate non appena l'app non le richiede più. Per altre informazioni, vedere Optimize Image Resources (Ottimizzare le risorse immagine).