快速拖动时 UIButton 超出边界限制

UIButton exceeds the limitation of boundaries when dragging very fast

我正在尝试在 UIButton 上实现具有边界限制的拖动控件。 我为此编写了以下代码。

- (void)onTouchDragInside:(UIButton*)btn withEvent:(UIEvent*)event{
  UITouch *touch = [[event touchesForView:btn] anyObject];
  CGPoint prevPos = [touch previousLocationInView:btn];
  CGPoint pos = [touch locationInView:btn];
  float dX = pos.x-prevPos.x;

  if (btn.frame.origin.x >= buttonOffPosition && btn.frame.origin.x <= buttonOnPosition) {
    btn.center=CGPointMake(btn.center.x+dX, btn.center.y);
    NSLog(@"buttonOffPos: %f", buttonOffPosition);
    NSLog(@"btn.center.x+dX: %f", btn.center.x+dX);
    NSLog(@"buttonOnPos: %f", buttonOnPosition);
  }
}

这几乎可以正常工作。但是只有当按钮被拖动非常快时,它才超过限制buttonOffPositionbuttonOnPosition

这是我要解决的问题。有什么好的方法可以解决这个问题吗?

非常感谢您的想法和帮助。

如果您希望代码将按钮的位置限制在两个值之间,您需要检查处理此触摸事件后按钮的最终静止点是什么,而不是检查它当前的位置。如果它当前在移动范围内,那么你将它移动 1000,它在最后将不再在范围内,但你允许它移动到那里,因为你没有检查终点。

您可以通过多种方式执行此操作。我想到的最简单的是:

- (void)onTouchDragInside:(UIButton*)btn withEvent:(UIEvent*)event{
  UITouch *touch = [[event touchesForView:btn] anyObject];
  CGPoint prevPos = [touch previousLocationInView:btn];
  CGPoint pos = [touch locationInView:btn];
  float dX = pos.x-prevPos.x;

  //Get the new origin after this motion
  float newXOrigin = btn.frame.origin.x + dX;
  //Make sure it's within your two bounds
  newXOrigin = MIN(newXOrigin,buttonOnPosition);
  newXOrigin = MAX(newXOrigin,buttonOffPosition);
  //Now get the new dX value staying in bounds
  dX = newXOrigin - btn.frame.origin.x;

  btn.center=CGPointMake(btn.center.x+dX, btn.center.y);
}

当您将按钮从一个方向拖动到另一个方向时,此方法会导致您的手指不再位于按钮内,但我会把这个问题留给您的下一个问题。

编辑:

以下是我如何让它更具可读性。这只是我的意见,与代码的工作方式无关。除了修改您的代码之外,我还会为按钮对象创建一个缓存起点并从中执行所有运动事件。这样,即使您的手指继续移动,如果您的按钮停止移动,那么当您的手指返回时,按钮会留在您的手指上。当前的解决方案是,一旦您的手指改变方向,即使您的手指现在远离按钮,按钮也会再次开始移动。但这样做对您来说将是一个很大的代码更改。

- (void)onTouchDragInside:(UIButton*)btn withEvent:(UIEvent*)event{
  //This code can go awry if there is more than one finger on the screen, careful
  UITouch *touch = [[event touchesForView:btn] anyObject];
  CGPoint prevPos = [touch previousLocationInView:btn];
  CGPoint pos = [touch locationInView:btn];
  float dX = pos.x-prevPos.x;

  //Get the original position of the button
  CGRect buttonFrame = btn.frame;

  buttonFrame.origin.x += dX;
  //Make sure it's within your two bounds
  buttonFrame.origin.x = MIN(buttonFrame.origin.x,buttonOnPosition);
  buttonFrame.origin.x = MAX(buttonFrame.origin.x,buttonOffPosition);

  //Set the button's new frame if we need to
  if(buttonFrame.origin.x != btn.frame.origin.x)
      btn.frame = buttonFrame
}