Reputation: 135
My question is regarding the PanGestureRecognizer on Xamarin.Forms, specifically on UWP. The pan gesture works great and the menu slides in and out but if you move the mouse cursor outside of the application window it does not trigger GestureStatus.Canceled, or GestureStatus.Completed. I've simplified the code below because it is not important. The pan gesture is working correctly and the menu is sliding in and out with the pan. The issue is it is not triggering anything if you move the cursor outside of the app window.
Code below:
panContainer is a simple ContentView.
var panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += PanUpdated;
panContainer.GestureRecognizers.Add(panGesture);
private void PanUpdated(object sender,PanUpdatedEventArgs e) {
switch(e.StatusType) {
case GestureStatus.Started:
break;
case GestureStatus.Running:
menuLayout.TranslationX = (float)e.TotalX;
break;
case GestureStatus.Completed:
case GestureStatus.Canceled: //I assumed this would be called!
if(menuLayout.TranslationX < 100) {
Close();
} else {
Open();
}
break;
}
}
Thanks in advance!
Upvotes: 4
Views: 1599
Reputation: 1118
Workable solution based on the previous comment
//Shared part
public class PanOutsideWindowEffect : RoutingEffect
{
public event EventHandler<PanUpdatedEventArgs> PanUpdated;
public PanOutsideWindowEffect() : base($"{ResolutionGroupName.Organization}.{nameof(PanOutsideWindowEffect)}")
{
}
public void SendPanCancel()
{
PanUpdated?.Invoke(this, new PanUpdatedEventArgs(GestureStatus.Canceled, 0));
}
}
//UWP part
public class PanOutsideWindowEffect : PlatformEffect
{
private FrameworkElement frameworkElement;
private MobileApp.Effects.PanOutsideWindowEffect effect;
protected override void OnAttached()
{
frameworkElement = Control == null ? Container : Control;
effect = (MobileApp.Effects.PanOutsideWindowEffect)Element.Effects.First(e => e is MobileApp.Effects.PanOutsideWindowEffect);
if (frameworkElement != null)
{
frameworkElement.PointerExited += OnPointerExited;
}
}
protected override void OnDetached()
{
if (frameworkElement != null)
{
frameworkElement.PointerExited -= OnPointerExited;
}
}
private void OnPointerExited(object sender, PointerRoutedEventArgs args)
{
effect?.SendPanCancel();
}
}
Upvotes: 0
Reputation: 32785
if you move the mouse cursor outside of the application window it does not trigger GestureStatus.Canceled, or GestureStatus.Completed. I've simplified the code below because it is not important. The pan gesture is working correctly and the menu is sliding in and out with the pan. The issue is it is not triggering anything if you move the cursor outside of the app window.
I have tested your code and reproduce the issue. I tried to find the cause of the problem in the source code. I found the following code.
void OnPointerCanceled(object sender, PointerRoutedEventArgs e)
{
uint id = e.Pointer.PointerId;
if (_fingers.Contains(id))
_fingers.Remove(id);
PinchComplete(false);
PanComplete(false);
}
void OnPointerExited(object sender, PointerRoutedEventArgs e)
{
uint id = e.Pointer.PointerId;
if (_fingers.Contains(id))
_fingers.Remove(id);
PinchComplete(true);
PanComplete(true);
}
void OnPointerPressed(object sender, PointerRoutedEventArgs e)
{
uint id = e.Pointer.PointerId;
if (!_fingers.Contains(id))
_fingers.Add(id);
}
void OnPointerReleased(object sender, PointerRoutedEventArgs e)
{
uint id = e.Pointer.PointerId;
if (_fingers.Contains(id))
_fingers.Remove(id);
PinchComplete(true);
PanComplete(true);
}
The PanComplete
method will be invoked when you PointerExited
,ManipulationCompleted
etc. But it has not been invoked when the pointer exited. And then I tried to test PointerExited
and ManipulationCompleted
event in uwp native project. Both are working properly.
<Border Width="200" Height="200" Background="Red" PointerEntered="Border_PointerEntered" PointerExited="Border_PointerExited" ManipulationCompleted="Border_ManipulationCompleted"/>
So,there may be some issues with xamarin.
Upvotes: 3