Xamarin.Forms触摸位置获取及手势处理API相关问题咨询
1. Xamarin.Forms原生触摸位置获取、手势识别API支持情况
Xamarin.Forms 内置了基础手势识别的原生API,开箱提供的识别器包括TapGestureRecognizer、PinchGestureRecognizer、PanGestureRecognizer、SwipeGestureRecognizer、DragGestureRecognizer、DropGestureRecognizer,覆盖点击、捏合缩放、平移拖拽、滑动、拖放等常规交互场景。
但原生API存在明显能力边界:默认没有在共享代码层暴露实时触摸位置获取接口,也不支持长按、双指旋转等进阶手势的直接识别。如果要实现触摸坐标跟踪、多指交互这类需求,纯原生方案只能通过各平台自定义渲染器重写平台层触摸事件自行封装,无法直接在共享项目中写逻辑。
2. MR.Gestures是否为触摸交互最优解决方案
MR.Gestures是Xamarin生态中成熟度较高的商用触摸处理库,确实支持在共享代码层直接处理长按、旋转、多指跟踪、实时坐标获取等原生未覆盖的场景,API封装简洁,对低版本Xamarin.Forms的兼容性较好,在Xamarin发展早期是很多开发者省却平台适配成本的首选。
但它不存在绝对的“最优”属性:
- 它是付费商业库,商用场景需要购买授权,使用有成本
- 项目更新节奏偏慢,尤其是Xamarin向.NET MAUI迭代的阶段,长期适配性存在不确定性
- 如果项目仅需简单的触摸坐标获取能力,引入该类重体量第三方库的性价比极低
3. 支持共享代码编写的其他触摸处理可选方案
- SkiaSharp自带触摸接口:如果项目本身使用SkiaSharp做自绘内容,可直接调用
SKCanvasView自带的Touch事件,在共享代码层获取所有触摸点的状态、坐标、动作类型,不需要额外引入其他依赖,跨平台表现一致,轻量无授权成本。 - 开源社区触摸库:比如TouchTracking、Xamarin.Forms.TouchEffect这类MIT协议的开源实现,通过附加效果(Effect)实现跨平台触摸事件透传,支持在共享层获取触摸位置、跟踪多指动作,覆盖绝大多数常规触摸交互需求,无商用限制。
- 社区工具包扩展:Xamarin.CommunityToolkit中也提供了部分手势、触摸相关的扩展实现,和官方框架兼容性更好,后续如果项目迁移到.NET MAUI,代码改造成本极低。
- 自定义Effect封装:如果触摸需求非常简单,完全可以自行实现一个轻量TouchEffect,仅需在各平台用几十行代码把原生触摸事件透传到共享层即可,无第三方依赖,逻辑完全可控。
4. Xamarin.Forms获取所有触摸点坐标的实现方式
无第三方依赖的原生实现
核心逻辑是通过自定义Effect或自定义渲染器,在各平台层捕获原生触摸事件,遍历所有活跃触摸点拿到原始坐标后,转换为Xamarin.Forms统一的设备无关单位(DP),再透传到共享层即可:
- Android端:重写对应原生View的
OnTouch回调,从MotionEvent对象中遍历所有Pointer索引,通过GetX()/GetY()方法获取每个触摸点的原始像素坐标,完成单位转换后回传。 - iOS端:重写原生View的
TouchesBegan/TouchesMoved/TouchesEnded方法,遍历事件参数中UITouch集合,通过LocationInView方法获取每个触摸点坐标,转换单位后回传。 - UWP端:重写原生控件的
PointerPressed/PointerMoved/PointerReleased事件,遍历当前活跃的Pointer对象获取坐标,转换单位后回传。
基于第三方库的快速实现
如果使用TouchTracking这类开源触摸库,不需要自行编写平台层适配代码,直接在共享层订阅触摸事件,事件参数会直接携带当前所有活跃触摸点的集合,遍历即可拿到每个点的ID、坐标、动作状态,示例代码:
// 共享层触摸事件处理示例 touchEffect.TouchAction += (s, args) => { // 遍历当前屏幕上所有活跃触摸点 foreach (var touch in args.Touches) { var touchId = touch.Id; var coordinateX = touch.Location.X; var coordinateY = touch.Location.Y; var touchState = touch.ActionType; // 编写自定义坐标处理逻辑 } };
注意:所有平台层拿到的原始像素坐标必须做单位转换,否则不同分辨率设备上获取的坐标值会和Xamarin.Forms布局的逻辑坐标存在偏差,无法直接用于布局计算。
内容的提问来源于stack exchange,提问作者Akram Talmoudi

