MAUI中左右点击按压/释放事件的检测问题
区分MAUI中Windows和macOS的左右点击手势并追踪按压状态
要同时实现左右点击区分、按压状态追踪的需求,最直接的方案是基于平台原生事件封装自定义手势识别器,绕开MAUI内置手势的局限性。以下是具体实现步骤:
自定义手势识别器(推荐)
通过封装平台原生的指针/鼠标事件,我们可以同时获取按键类型和按压状态变化。
1. 共享项目中定义核心手势类
创建跨平台的手势抽象,包含按压/释放事件和按键类型枚举:
using System; namespace YourAppNamespace { public class CustomPointerGestureRecognizer : GestureRecognizer { public event EventHandler<PointerButtonEventArgs> PointerDown; public event EventHandler<PointerButtonEventArgs> PointerUp; internal void RaisePointerDown(PointerButton button) { PointerDown?.Invoke(this, new PointerButtonEventArgs(button)); } internal void RaisePointerUp(PointerButton button) { PointerUp?.Invoke(this, new PointerButtonEventArgs(button)); } } public enum PointerButton { Left, Right, Other } public class PointerButtonEventArgs : EventArgs { public PointerButton Button { get; } public PointerButtonEventArgs(PointerButton button) => Button = button; } }
2. Windows平台实现手势Handler
在Platforms/Windows目录下创建平台特定的Handler,对接WinUI的指针事件:
using Microsoft.Maui.Handlers; using Microsoft.UI.Xaml.Input; using YourAppNamespace; namespace YourAppNamespace.Platforms.Windows { public class CustomPointerGestureHandler : GestureHandler<CustomPointerGestureRecognizer, Microsoft.UI.Xaml.UIElement> { protected override void ConnectHandler(Microsoft.UI.Xaml.UIElement platformView) { base.ConnectHandler(platformView); platformView.PointerPressed += OnPointerPressed; platformView.PointerReleased += OnPointerReleased; } protected override void DisconnectHandler(Microsoft.UI.Xaml.UIElement platformView) { platformView.PointerPressed -= OnPointerPressed; platformView.PointerReleased -= OnPointerReleased; base.DisconnectHandler(platformView); } private void OnPointerPressed(object sender, PointerRoutedEventArgs e) { var point = e.GetCurrentPoint((Microsoft.UI.Xaml.UIElement)sender); var button = point.Properties.IsRightPressed ? PointerButton.Right : point.Properties.IsLeftPressed ? PointerButton.Left : PointerButton.Other; GestureRecognizer.RaisePointerDown(button); } private void OnPointerReleased(object sender, PointerRoutedEventArgs e) { var point = e.GetCurrentPoint((Microsoft.UI.Xaml.UIElement)sender); var button = point.Properties.IsRightPressed ? PointerButton.Right : point.Properties.IsLeftPressed ? PointerButton.Left : PointerButton.Other; GestureRecognizer.RaisePointerUp(button); } } }
3. macOS平台实现手势Handler
在Platforms/MacCatalyst目录下创建对接AppKit鼠标事件的Handler:
using AppKit; using Microsoft.Maui.Handlers; using YourAppNamespace; namespace YourAppNamespace.Platforms.MacCatalyst { public class CustomPointerGestureHandler : GestureHandler<CustomPointerGestureRecognizer, NSView> { protected override void ConnectHandler(NSView platformView) { base.ConnectHandler(platformView); platformView.MouseDown += OnMouseDown; platformView.MouseUp += OnMouseUp; } protected override void DisconnectHandler(NSView platformView) { platformView.MouseDown -= OnMouseDown; platformView.MouseUp -= OnMouseUp; base.DisconnectHandler(platformView); } private void OnMouseDown(object sender, NSEventEventArgs e) { var button = e.Event.ButtonNumber switch { 0 => PointerButton.Left, 2 => PointerButton.Right, _ => PointerButton.Other }; GestureRecognizer.RaisePointerDown(button); } private void OnMouseUp(object sender, NSEventEventArgs e) { var button = e.Event.ButtonNumber switch { 0 => PointerButton.Left, 2 => PointerButton.Right, _ => PointerButton.Other }; GestureRecognizer.RaisePointerUp(button); } } }
4. 注册手势Handler并使用
在MauiProgram.cs中注册平台Handler:
using YourAppNamespace.Platforms.MacCatalyst; using YourAppNamespace.Platforms.Windows; var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureMauiHandlers(handlers => { #if WINDOWS handlers.AddHandler<CustomPointerGestureRecognizer, CustomPointerGestureHandler>(); #endif #if MACCATALYST handlers.AddHandler<CustomPointerGestureRecognizer, CustomPointerGestureHandler>(); #endif });
在XAML中绑定手势并处理事件:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:YourAppNamespace" x:Class="YourAppNamespace.MainPage"> <Frame WidthRequest="300" HeightRequest="300" BackgroundColor="LightSkyBlue"> <Frame.GestureRecognizers> <local:CustomPointerGestureRecognizer PointerDown="OnPointerDown" PointerUp="OnPointerUp"/> </Frame.GestureRecognizers> <Label Text="Click with Left/Right Button" HorizontalOptions="Center" VerticalOptions="Center"/> </Frame> </ContentPage>
后台代码处理按压/释放逻辑:
private void OnPointerDown(object sender, PointerButtonEventArgs e) { switch (e.Button) { case PointerButton.Left: // 左键按下时的逻辑,比如高亮控件 break; case PointerButton.Right: // 右键按下时的逻辑,比如显示上下文菜单前置状态 break; } } private void OnPointerUp(object sender, PointerButtonEventArgs e) { switch (e.Button) { case PointerButton.Left: // 左键释放完成点击的逻辑 break; case PointerButton.Right: // 右键释放完成点击的逻辑 break; } }
注意事项
- macOS上,无论是物理右键按钮还是
Control+左键模拟右键,都会被识别为PointerButton.Right - 可以根据需求扩展自定义手势,比如添加指针位置、按压压力等额外信息
内容的提问来源于stack exchange,提问作者GMachine
相关产品推荐
相关产品推荐

