UWP InkCanvas触摸模式下自定义手势实现方法咨询
解决UWP InkCanvas触摸模式下无法使用自定义手势的问题
这个问题我之前踩过坑!核心原因很简单:当你把InkPresenter.InputDeviceTypes设为CoreInputDeviceTypes.Touch时,系统会默认将所有触摸输入直接路由给笔迹绘制逻辑,你的PointerPressed这类事件会被InkPresenter拦截,根本轮不到你的自定义代码处理。下面给你两种靠谱的解决方案,亲测有效:
方案一:使用UnprocessedInput处理手势(官方推荐)
InkPresenter专门提供了UnprocessedInput属性,用来处理那些还没被笔迹系统处理的输入,完美适配手势识别场景。你可以通过它来监听触摸输入,判断是否是手势,再决定要不要交给笔迹绘制。
示例代码如下:
private Point _gestureStartPoint; private bool _isGestureDetected; private void ink1_Loaded(object sender, RoutedEventArgs e) { // 先设置好触摸输入类型 ink1.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Touch; // 监听UnprocessedInput的触摸事件 ink1.InkPresenter.UnprocessedInput.PointerPressed += UnprocessedInput_PointerPressed; ink1.InkPresenter.UnprocessedInput.PointerMoved += UnprocessedInput_PointerMoved; ink1.InkPresenter.UnprocessedInput.PointerReleased += UnprocessedInput_PointerReleased; } private void UnprocessedInput_PointerPressed(InkUnprocessedInput sender, PointerEventArgs args) { // 记录手势起始点 var point = args.CurrentPoint.Position; _gestureStartPoint = new Point(point.X, point.Y); _isGestureDetected = false; } private void UnprocessedInput_PointerMoved(InkUnprocessedInput sender, PointerEventArgs args) { if (_isGestureDetected) return; var currentPoint = args.CurrentPoint.Position; // 计算移动距离,这里设个阈值(比如20像素)判断是否是滑动手势 double deltaX = Math.Abs(currentPoint.X - _gestureStartPoint.X); double deltaY = Math.Abs(currentPoint.Y - _gestureStartPoint.Y); if (deltaX > 20 || deltaY > 20) { // 检测到滑动手势,执行你的逻辑 HandleSwipeGesture(deltaX > deltaY ? (currentPoint.X > _gestureStartPoint.X ? "右滑" : "左滑") : (currentPoint.Y > _gestureStartPoint.Y ? "下滑" : "上滑")); _isGestureDetected = true; // 标记输入已处理,阻止笔迹绘制 args.Handled = true; } } private void UnprocessedInput_PointerReleased(InkUnprocessedInput sender, PointerEventArgs args) { if (!_isGestureDetected) { // 没有检测到滑动,判断是否是点击/双击手势 var currentPoint = args.CurrentPoint.Position; double delta = Math.Sqrt(Math.Pow(currentPoint.X - _gestureStartPoint.X, 2) + Math.Pow(currentPoint.Y - _gestureStartPoint.Y, 2)); if (delta < 10) { // 点击手势,执行你的逻辑 HandleTapGesture(); args.Handled = true; } } } // 自定义手势处理方法 private void HandleSwipeGesture(string direction) { // 这里写你的滑动手势逻辑,比如切换页面、删除笔迹等 Debug.WriteLine($"检测到{direction}手势"); } private void HandleTapGesture() { // 这里写你的点击手势逻辑 Debug.WriteLine("检测到点击手势"); }
方案二:临时切换InputDeviceTypes(应急方案)
如果你的手势逻辑比较简单,也可以在检测到可能的手势时,临时把InkPresenter的输入类型改成None,处理完手势再改回Touch。不过这个方法可能会有轻微的延迟,不如方案一流畅:
private void ink1_PointerPressed(object sender, PointerRoutedEventArgs e) { var pointerPoint = e.GetCurrentPoint(ink1); if (pointerPoint.PointerDevice.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Touch) { // 临时关闭触摸输入,避免笔迹绘制 ink1.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.None; // 记录起始点,后续判断手势 _gestureStartPoint = pointerPoint.Position; } } private void ink1_PointerReleased(object sender, PointerRoutedEventArgs e) { var pointerPoint = e.GetCurrentPoint(ink1); double delta = Math.Sqrt(Math.Pow(pointerPoint.Position.X - _gestureStartPoint.X, 2) + Math.Pow(pointerPoint.Position.Y - _gestureStartPoint.Y, 2)); if (delta < 10) { // 点击手势处理 HandleTapGesture(); } else { // 滑动手势处理 HandleSwipeGesture(/* 判断方向 */); } // 恢复触摸输入,允许笔迹绘制 ink1.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Touch; e.Handled = true; }
关键注意点
- 一定要用
args.Handled = true来标记输入已处理,这样InkPresenter就不会再把这个触摸事件当成笔迹来处理了。 - 手势的阈值(比如滑动距离、点击误差范围)可以根据你的需求调整,让手势识别更精准。
内容的提问来源于stack exchange,提问作者Kay
相关产品推荐
相关产品推荐

