我的问题是关于Xamarin.Forms上的PanGestureRecognizer,特别是关于UWP的问题。平移手势很有效,菜单可以滑入和滑出,但如果将鼠标光标移动到应用程序窗口之外,则不会触发GestureStatus.Canceled或GestureStatus.Completed。我已经简化了下面的代码,因为它并不重要。平移手势正常工作,菜单随着平底锅滑入和滑出。问题是,如果将光标移到应用程序窗口之外,它不会触发任何内容。
以下代码:
panContainer是一个简单的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;
}
}
提前致谢!
答案 0 :(得分:2)
如果将鼠标光标移动到应用程序窗口之外,则不会触发GestureStatus.Canceled或GestureStatus.Completed。我已经简化了下面的代码,因为它并不重要。平移手势正常工作,菜单随着平底锅滑入和滑出。问题是,如果将光标移到应用程序窗口之外,它不会触发任何内容。
我已经测试了您的代码并重现了该问题。我试图在源代码中找到问题的原因。我找到了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);
}
当您PanComplete
,PointerExited
等时,将调用ManipulationCompleted
方法。但是当指针退出时,它尚未被调用。然后我尝试在uwp本机项目中测试PointerExited
和ManipulationCompleted
事件。两者都运作正常。
<Border Width="200" Height="200" Background="Red" PointerEntered="Border_PointerEntered" PointerExited="Border_PointerExited" ManipulationCompleted="Border_ManipulationCompleted"/>
因此,xamarin可能存在一些问题。
答案 1 :(得分:0)
基于之前评论的可行解决方案
//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();
}
}