通过 TouchesBegan/TouchesMoved 的触摸输入(笔/手指)有很大的初始间隙

Posted

技术标签:

【中文标题】通过 TouchesBegan/TouchesMoved 的触摸输入(笔/手指)有很大的初始间隙【英文标题】:Touch input (pen/finger) via TouchesBegan/TouchesMoved has big initial gaps 【发布时间】:2020-11-08 21:59:28 【问题描述】:

我正在为 ios 开发一个应用程序。所有内容的最新版本。

我正在添加一些触摸输入 - 基本上是绘制一些形状和突出显示事物的能力。我有一个 UIScrollView ,其中包含一个 UIView ,其他对象被绘制或放置在该 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 期间会添加积分。请注意,first 点有一个巨大的跳跃(参见“向量”,这是与前一点的差异)。这发生在与 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), timestamp(70489.10), speed(1505.20), force(1.43)
2020-11-09 10:16:51.105 PenApp[1499:449121] Added point: Point(811.00, 536.00), Vector(0.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, 5.00), width(2.86), timestamp(70489.12), speed(1346.29), force(1.43)

我看到其他人评论了第一点差距,并建议跳过第一点。我不能简单地忽略第一点——那是我用笔/手指触摸屏幕开始曲线的地方。在绘图开始之前跳过它会导致很大的差距(我试过了)。 Example of other person seeing problem

影响是我的笔实际上在整个过程中都在跟踪一条曲线,但是我在数据中得到了这个巨大的初始差距,所以即使我实际上是使用贝塞尔曲线来绘制曲线(具有不同的粗细),我实际上由于缺少中间点,在屏幕上绘制基本上需要笔直。这是一个示例 - 从底部开始绘制:

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

有没有人看到这个并且可能有一些指示? 谢谢。 保罗

附录:我正在尝试使用 UIGestureRecognizer 的自定义子类,its 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)。我的绘图现在非常流畅 - 这是一个示例:

【问题讨论】:

您好,如果使用Touches时出现这种现象,您也可以在Github中[这里(]github.com/xamarin/xamarin-macios/issues)提交,寻求更多帮助。 @JuniorJiang-MSFT - 完成。 好的,你可以在这里分享链接,其他人也可以在那里跟进。 好点。 github.com/xamarin/xamarin-macios/issues/10072 @Paul 你解决了这个问题吗?请解决方案 【参考方案1】:

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

所以上面附录#2中概述的源代码和解决方案 彻底解决这个问题。

所以我认为这个已经关闭了。

【讨论】:

好吧,如果是这样,您可以将其标记为答案。其他人会知道在 iOS 设备上显示的原因。【参考方案2】:

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

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

scrollView.delaysContentTouches = false

但不确定如何在 Xamarin 中执行此操作。

【讨论】:

以上是关于通过 TouchesBegan/TouchesMoved 的触摸输入(笔/手指)有很大的初始间隙的主要内容,如果未能解决你的问题,请参考以下文章

下拉框多选框单选框 通过TagHelper绑定数据

酶:测试孩子通过安装渲染失败,但通过浅时通过

java是通过值传递,也就是通过拷贝传递——通过方法操作不同类型的变量加深理解

通过代码进行 Spring 配置与通过注释进行配置

如何理解“不要通过共享内存来通信,而应该通过通信来共享内存”?

通过邮递员通过 API 使用 Rails 主动存储上传文件(.pdf、.jpg 等)? (不通过 Rails 视图)