Olá, neste post irei demonstrar como você pode implementar zoom nas imagens em suas aplicações Xamarin.Forms de uma maneira fácil e rápida utilizando custom renderer.
Comece criando a classe estática chamada “DoubleExtensions” no projeto compartilhado.
DoubleExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
namespace DemoZoomImage | |
{ | |
public static class DoubleExtensions | |
{ | |
public static double Clamp(this double self, double min, double max) | |
{ | |
return Math.Min(max, Math.Max(self, min)); | |
} | |
} | |
} |
Em seguida crie a classe “PinchToZoomContainer” em seu projeto compartilhado, ela será responsável em capturar o GestureStatus e aplicar o zoom na imagem.
PinchToZoomContainer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Xamarin.Forms; | |
namespace DemoZoomImage | |
{ | |
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; | |
} | |
} | |
} | |
} |
Xaml
Para utilizar no arquivo xaml, adicione uma Image dentro do PinchToZoomContainer.Content como demonstrado a seguir.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8" ?> | |
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" | |
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | |
xmlns:local="clr-namespace:DemoZoomImage" | |
x:Class="DemoZoomImage.MainPage"> | |
<Grid Padding="20"> | |
<local:PinchToZoomContainer> | |
<local:PinchToZoomContainer.Content> | |
<Image Source="wallpaper.jpg"/> | |
</local:PinchToZoomContainer.Content> | |
</local:PinchToZoomContainer> | |
</Grid> | |
</ContentPage> |
Resultado
Esse e todos os exemplos deste blog encontram-se disponíveis no GitHub.