maui-linux/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issu.../Bugzilla57515.cs

147 строки
4.3 KiB
C#

using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System;
#if UITEST
using Xamarin.UITest;
using Xamarin.Forms.Core.UITests;
using NUnit.Framework;
#endif
namespace Xamarin.Forms.Controls.Issues
{
#if UITEST
[Category(UITestCategories.Gestures)]
#endif
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Bugzilla, 57515, "PinchGestureRecognizer not getting called on Android ", PlatformAffected.Android)]
public class Bugzilla57515 : TestContentPage
{
const string ZoomImage = "zoomImg";
const string ZoomContainer = "zoomContainer";
protected override void Init()
{
var layout = new Grid
{
RowDefinitions = new RowDefinitionCollection
{
new RowDefinition { Height = 80 },
new RowDefinition { Height = GridLength.Star }
}
};
var scaleLabel = new Label();
layout.Children.Add(scaleLabel);
var pinchToZoomContainer = new PinchToZoomContainer
{
Margin = new Thickness(80),
AutomationId = ZoomContainer,
Content = new Image
{
AutomationId = ZoomImage,
Source = ImageSource.FromFile("oasis.jpg")
}
};
Grid.SetRow(pinchToZoomContainer, 1);
layout.Children.Add(pinchToZoomContainer);
scaleLabel.BindingContext = pinchToZoomContainer;
scaleLabel.SetBinding(Label.TextProperty, new Binding("CurrentScale"));
Content = layout;
}
class PinchToZoomContainer : ContentView
{
public static readonly BindableProperty CurrentScaleProperty =
BindableProperty.Create("CurrentScale", typeof(double), typeof(PinchToZoomContainer), 1.0);
public double CurrentScale
{
get { return (double)GetValue(CurrentScaleProperty); }
set { SetValue(CurrentScaleProperty, value); }
}
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;
}
}
}
#if UITEST
[Test]
public void Bugzilla57515Test()
{
RunningApp.WaitForElement(ZoomContainer);
RunningApp.WaitForElement("1");
RunningApp.PinchToZoomIn(ZoomContainer);
RunningApp.WaitForNoElement("1"); // The scale should have changed during the zoom
}
#endif
}
public static class DoubleExtensions
{
public static double Clamp(this double self, double min, double max)
{
return Math.Min(max, Math.Max(self, min));
}
}
}