为啥使用 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 效果很好! 您还需要将UILongPressGestureRecognizer
的allowableMovement
设置为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?为啥不直接更改渲染坐标?
为啥在参数周围使用 /*、*/ 以及为啥在提取数组长度时使用 >>>? [复制]
为啥我们使用 hadoop mapreduce 进行数据处理?为啥不在本地机器上做呢?