Last active
April 20, 2022 17:52
-
-
Save DamianSuess/fa38a2f952ca5f589de2d3e9a441f370 to your computer and use it in GitHub Desktop.
Xamarin.Forms - Pinch and Zoom
This file contains hidden or 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
<!-- | |
Based on the article: | |
* https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/gestures/pinch | |
* https://github.com/xamarin/xamarin-forms-samples/tree/master/WorkingWithGestures/PinchGesture | |
--> | |
<StackLayout> | |
<Label Text="Xamarin Forms- Pinch Gesture in Android and UWP" | |
VerticalOptions="Center" HorizontalOptions="Center" | |
FontSize="Large" | |
TranslationX="0" TranslationY="50" /> | |
<Image Source="nature.jpg" | |
HeightRequest="200" WidthRequest="200" | |
VerticalOptions="Center" HorizontalOptions="Center" | |
TranslationX="0" TranslationY="100"> | |
<Image.GestureRecognizers> | |
<PinchGestureRecognizer PinchUpdated="OnPinchUpdated" /> | |
</Image.GestureRecognizers> | |
</Image> | |
</StackLayout> |
This file contains hidden or 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
/* | |
Based on the article: | |
* https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/gestures/pinch | |
* https://github.com/xamarin/xamarin-forms-samples/tree/master/WorkingWithGestures/PinchGesture | |
*/ | |
void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e) | |
{ | |
if (e.Status == GestureStatus.Started) | |
{ | |
startScale = Content.Scale; | |
Content.AnchorX = 0; | |
Content.AnchorY = 0; | |
} | |
if (e.Status == GestureStatus.Running) | |
{ | |
currentScale += (e.Scale - 1) * startScale; | |
currentScale = Math.Max(1, currentScale); | |
// The ScaleOrigin is in relative coordinatesto the wrapped UI element. | |
double renderedX = Content.X + xOffset; | |
double deltaX = renderedX / Width; | |
double deltaWidth = Width / (Content.Width * startScale); | |
double originX = (e.ScaleOrigin.X - deltaX) * deltaWidth; | |
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 = Math.Min(0, Math.Max(targetX, -Content.Width * (currentScale - 1))); | |
Content.TranslationY = Math.Min(0, Math.Max(targetY, -Content.Height * (currentScale - 1))); | |
// Apply scale factor | |
Content.Scale = currentScale; | |
} | |
if (e.Status == GestureStatus.Completed) | |
{ // Store the deltas of the wrapped UI element | |
xOffset = Content.TranslationX; | |
yOffset = Content.TranslationY; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Trying to use this in conjunction with other controls that take the Pan/scroll gesture seems to fail. ScrollView and ListView for example grab the Pinch gesture even though they themselves don't Pinch but they do scroll/pan. So it seems like Pinch inherits/uses that gesture so it is grabbed by the wrapped control. This seems to make Pinch a very niche feature that can only work on very static views of Label and Image for example, but nothing more complex.
In other words - any way to wrap a ScrollView or ListView with a PinchToZoom and have it work?