Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1909, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Xamarin Certified Mobile Developer

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Xamarin.Forms: pinch-to-zoom di immagini

In Xamarin.Forms il controllo Image per la visualizzazione di immagini non supporta il pinch-to-zoom, ma questo è abbastanza normale.

La documentazione spiega come raggiungere l'obiettivo in modo abbastanza semplice, ovvero aggiungendo una gesture recognizer al controllo Image e poi puntando a un gestore che esegua il resize matematico dell'immagine.

Se però doveste visualizzare un'immagine che riempia la pagina, dovete agire a livello di contenitore. Il codice che vi riporto l'ho trovato nei forum di Xamarin, non è mio, purtroppo non trovo più il link originale ma non sarà difficile cercare.

Innanzitutto si crea un contenitore di livello più alto per supportare questa gestualità:

public class PinchToZoomContainer : ContentView
{
    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;
        }
    }
}

Poi lo si referenzia nello XAML utilizzando il namespace che lo dichiara:

xmlns:controls="clr-namespace:MyApp.Controls;assembly=MyApp" 

E lo si utilizza in modo abbastanza semplice:

  <ContentPage.Content>
    <Grid Padding="20">
      <local:PinchToZoomContainer>
        <local:PinchToZoomContainer.Content>
          <Image Source="Immagine.jpg" />
        </local:PinchToZoomContainer.Content>
      </local:PinchToZoomContainer>
    </Grid>
  </ContentPage.Content>

Come vedete, il controllo Image a questo punto va a far parte del nuovo contenitore.

Alessandro

Print | posted on martedì 13 settembre 2016 00:00 | Filed Under [ Xamarin ]

Powered by:
Powered By Subtext Powered By ASP.NET