为啥使用 UIPanGestureRecognizer 移动对象时会有延迟?

Posted

技术标签:

【中文标题】为啥使用 UIPanGestureRecognizer 移动对象时会有延迟?【英文标题】:Why is there a delay when moving object using UIPanGestureRecognizer?为什么使用 UIPanGestureRecognizer 移动对象时会有延迟? 【发布时间】:2012-05-23 21:24:15 【问题描述】:

我正在使用UIPanGestureRecognizer 移动UIView 对象——我的手指在屏幕上拖动了多少,我在同一方向上移动了多少视图(仅在 X 方向 - 向左或向右,Y 不变)。它工作正常,但(非常明显)延迟

下面是处理UIPanGestureRecognizer事件的方法:

-(void)movePages:(UIPanGestureRecognizer *)sender

    if (switchingMode == 1) 
        if ([sender state] == UIGestureRecognizerStateBegan) 
            fingerStartPosition = [sender locationInView:self.view].x;
            viewStartPosition = [[viewControllers objectAtIndex:activeViewControllerIndex] view].center;
        
        [[[[viewControllers objectAtIndex:activeViewControllerIndex] view] layer] setPosition:CGPointMake(viewStartPosition.x - (fingerStartPosition - [sender locationInView:self.view].x) , viewStartPosition.y)];            
    

我尝试使用其图层设置视图的位置,我还尝试设置框架,使用具有不同持续时间的动画,但一切都表现相同。知道为什么会出现这种延迟吗?

【问题讨论】:

您找到解决方案了吗?也有它 【参考方案1】:

使用UILongPressGestureRecognizer 并将minimumPressDuration 设置为0.0。这会立即识别,并且您会获得所有相同的更新,包括带有更新位置的 UIGestureRecognizerStateChanged

【讨论】:

我想补充一下——当表单被放大(缩放)时,我遇到了表单上的绘图字段的问题——如果你立即开始绘图,它会滚动,你必须在绘图前将手指放在适当的位置一秒钟。以 100% 的比例执行此操作并没有发生,它会立即开始绘制。用 UILongPressGestureRecognizer 替换 UIPanGestureRecognizer 效果很好! 您还需要将UILongPressGestureRecognizerallowableMovement 设置为CGFloat.infinity。否则,手势将在拖动一小段距离(10pt)后自行取消。 奇怪的是,为了解决与@EvilGeniusJamie 完全相同的问题,对我来说,这是我必须设置的 Slipp 提到的允许移动。一旦放大到 1.5,它需要越来越长的距离。我不得不以光速拖动以防止 UIpan 取消并能够触发 Move 事件。将其设置为无穷大确实有效。 但是使用这个解决方案,您将没有translation(in:) 方法,这就是我们需要UIPanGestureRecognizer 的原因:/ 它可以工作,但是使用长按识别器时没有velocity【参考方案2】:

我发现如果只使用常规的 touchesBegan、Moved 和 Ended,响应速度会更快。我什至对 UIGestureRecognizer 进行了子类化,但它仍然滞后于平移手势。即使 UIGestureRecognizer 中的 touchesBegan 会按时触发,状态更改也需要半秒才能更改其状态......使用普通的旧 TouchesBegan 似乎更快,特别是如果你的 cpu 正在做很多事情。

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)

    if touches.count == 1
    
        initialTouchLocation = (touches.first?.locationInView(self).x)!
    

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)

    if touches.count == 1
    
        let locationInView = touches.first?.locationInView(self)
        if !thresholdHit
        
            //this is the threshold for x movement in order to trigger the panning...
            if abs(initialTouchLocation - locationInView!.x) > 1
            
                thresholdHit = true
            
        
        else
        
            if (self.frame.width != CGFloat(screenSize))
            
                let panDelta = initialTouchLocation - locationInView!.x
            
        
    

【讨论】:

同意。就我而言,我想突出显示我正在拖动的项目。为了使它看起来不错,需要立即绘制高光。似乎 UIGestureRecognizer 的东西在将初始操作发送到目标时有点慢,这对我的用例来说根本没有用。 注意 - 如果您实际上是在移动视图,只需使用超级视图(.. 中的位置)来防止抖动【参考方案3】:

GestureRecognizer 在您将手指移动一些像素之前无法确定它是否是平移手势。我不知道确切的容差值,但这就是您感到延迟的原因。

文档:

平移手势是连续的。当允许的最小手指数移动到足以被视为平移时,它就开始了。

如果您想要即时移动,您可能需要使用touchesMoved: 构建自己的逻辑。

另一种方法可能是动画到第一个识别点。但这并不能消除延迟。 对于这种方法,您可以查看我在 github 上的 JDDroppableView。

【讨论】:

这不是拖动开始时的延迟我的意思是......当这个延迟结束,并且对象已经在移动时,它正在延迟移动。我拖动,对象开始移动,但有点慢,我必须等到对象到达所需位置

以上是关于为啥使用 UIPanGestureRecognizer 移动对象时会有延迟?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 glTranslatef?为啥不直接更改渲染坐标?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥在参数周围使用 /*、*/ 以及为啥在提取数组长度时使用 >>>? [复制]

为啥我们使用 hadoop mapreduce 进行数据处理?为啥不在本地机器上做呢?

为啥 CoreGui Roblox 锁定在 DataModel 中,为啥受信任的用户不能使用 CoreScripts?

为啥有人应该在 git commit 之前使用 git add?或者为啥有人应该使用 git add 呢?