通过TouchesBegan / TouchesMoved进行的触摸输入笔/手指初始间隙较大

问题描述

我正在为iOS开发一个应用程序。一切的最新版本。

我要添加一些触摸输入-基本上可以绘制一些形状并突出显示内容我有一个UIScrollView,其中包含一个UIView,在上面绘制或放置了其他对象。 UIView有一个子视图-一个自定义UIView,它是覆盖其全部内容的绘图画布。

我正在该画布中捕获touchesBegan / Moved / Cancelled / Ended例程。绘图,记录点,重绘,在压力,颜色等方面改变线宽都可以正常工作。

奇怪的是,我总是收到-Began消息,然后立即获得-Moved消息,并且跳转很大。然后事情似乎稳定下来,可以每8-10毫秒接收一次点了。

这里是一个示例: 首先-调用touchesBegan,在其中记录第一点。

2020-11-09 10:16:51.094 PenApp[1499:449121] TouchBegan: Point(656.50,380.00)
2020-11-09 10:16:51.094 PenApp[1499:449121] Added point: Point(656.50,380.00),Vector(0.00,0.00),width(1.00),timestamp(70488.92),speed(0.00),force(1.47)

现在在touchesMoved中添加点。请注意,第一点有一个很大的跳跃(请参阅“向量”,它与前一点有所不同)。这发生在与touchesBegan(51.094)相同的毫秒内。然后事情就解决了,以进行平滑跟踪。

2020-11-09 10:16:51.094 PenApp[1499:449121] Added point: Point(809.50,518.50),Vector(153.00,138.50),width(2.94),timestamp(70489.09),speed(1206.88),force(1.47)
2020-11-09 10:16:51.096 PenApp[1499:449121] Added point: Point(810.50,525.00),Vector(1.00,6.50),width(2.87),timestamp(70489.10),speed(1644.12),force(1.43)
2020-11-09 10:16:51.097 PenApp[1499:449121] Added point: Point(811.00,531.00),Vector(0.50,6.00),width(2.86),speed(1505.20),force(1.43)
2020-11-09 10:16:51.105 PenApp[1499:449121] Added point: Point(811.00,536.00),5.00),width(2.85),timestamp(70489.11),speed(1250.00),force(1.42)
2020-11-09 10:16:51.113 PenApp[1499:449121] Added point: Point(807.50,551.50),Vector(-3.50,15.50),width(2.84),timestamp(70489.12),speed(1222.33),force(1.42)
2020-11-09 10:16:51.122 PenApp[1499:449121] Added point: Point(805.50,556.50),Vector(-2.00,speed(1346.29),force(1.43)

我看到其他人对此第一点差距发表评论,并建议跳过第一点。我不能简单地忽略第一个点-那就是我用笔/手指触摸屏幕以开始绘制曲线的位置。跳过它会导致绘图开始之前有很大的差距(我尝试过)。 Example of other person seeing problem

影响是我的笔在整个过程中实际上一直在跟踪曲线,但是我在数据中得到了巨大的初始间隙,因此即使我实际上是在使用Beziers绘制曲线(具有变化的粗细),我实际上还是由于缺少中间点,因此在屏幕上绘制基本上需要笔直。这是一个示例-绘图从底部开始:

A curve with a large jump at the start

我没有其他正在运行的线程。这是非常一致的-它发生在每个图形上。我没有其他事件可以触发。我在外部滚动视图上设置了两指平移手势识别器,因此可以四处移动,而忽略了touches-功能中的多点触摸。但是,没有引发多点触摸事件。

有人见过这个并且可能有一些指示吗? 谢谢。 保罗

附录:我正在尝试使用UIGestureRecognizer的自定义子类,并且 touchesBegan / touchesMoved方法似乎被正确调用-开始时没有大的跳跃

附录^ 2:使用UIGestureRecognizer可以很好地工作,因此我将在此处复制代码。我不会添加答案,因为我不认为这可以回答实际的问题(为什么touches *有很大的差距)-而是更多的解决方法。使用笔势跟踪笔迹不会感觉很写-我的理解是,它们更适合高级操作(平移,对象选择,移动等)。

public class DrawingGestureRecognizer : UIGestureRecognizer
{
    DrawingView canvas;
    bool LineActive = false;

    public DrawingGestureRecognizer(DrawingView _canvas) : base()
    {
        canvas = _canvas;
    }

    public override void touchesBegan(NSSet touches,UIEvent evt)
    {
        Console.WriteLine("DrawingGestureRecognizer: TouchBegin");
        if (LineActive)
        {
            //  Looks line another line has started - probably a multi-touch starting.
            canvas.CurveCancelled(touches,evt);
            LineActive = false;
            return;
        }
        if (touches.Count != 1)
        {
            //  Multi-touch... so ignore.
            base.touchesBegan(touches,evt);
            return;
        }
        LineActive = true;
        canvas.CurveBegan(touches,evt);
    }
    public override void touchesMoved(NSSet touches,UIEvent evt)
    {
        Console.WriteLine("DrawingGestureRecognizer Moved");
        if (!LineActive || touches.Count != 1)
        {
            base.touchesMoved(touches,evt);
            return;
        }
        canvas.CurveMoved(touches,evt);
    }
    public override void touchesEnded(NSSet touches,UIEvent evt)
    {
        Console.WriteLine("DrawingGestureRecognizer Ended");
        if (!LineActive || touches.Count != 1)
        {
            //  A line was not active and we got an Ended message? Hand it on.
            //  If a line was active,but it switched to multitouch? Hand it on.
            base.touchesMoved(touches,evt);
            LineActive = false;
            return;
        }
        canvas.CurveEnded(touches,evt);
        LineActive = false;
    }
    public override void touchesCancelled(NSSet touches,UIEvent evt)
    {
        Console.WriteLine("DrawingGestureRecognizer Cancelled");
        if (!LineActive || touches.Count != 1)
        {
            base.touchesCancelled(touches,evt);
            LineActive = false;
            return;
        }
        canvas.CurveCancelled(touches,evt);
        LineActive = false;
    }
}

在我的DrawingView中,我将touches *重命名为Curve *(例如touchesBegan-> CurveBegan)。现在我的绘图非常流畅-这是一个示例:

Smooth curve,with force based width

解决方法

您可以从GitHub链接的注释中看到:
https://github.com/xamarin/xamarin-macios/issues/10072
该问题很可能是iOS固有的。

因此,上述附录2中概述了源代码和解决方案 将彻底解决此问题。

所以我认为这是封闭的。

,

我在 iOS 应用中遇到了同样的问题,因为我在其中捕获触摸事件的视图嵌入在滚动视图中。

这可以通过设置 ScrollView 不延迟触摸事件来解决:

scrollView.delaysContentTouches = false

不知道如何在 Xamarin 中做到这一点。