【问题标题】:Drag and drop objects and return them to their original position拖放对象并将其返回到原始位置
【发布时间】:2011-08-03 10:10:44
【问题描述】:

我正在尝试拖动图像并在释放后让它返回到原来的位置。到目前为止,我可以通过使用以下代码将图像创建为按钮来拖动图像:(如该问题的答案所示:Basic Drag and Drop in iOS

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(imageTouch:withEvent:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
[button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal];
[self.view addSubview:button];

后来我定义:

- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
    CGPoint point = [[[event allTouches] anyObject] locationInView:self.view];
    UIControl *control = sender;
    control.center = point;
}

释放后如何让它回到原来的位置?,对于初学者,我将保存每个图像应该返回的位置,但是,无论如何都要指示 UIImage 从它的当前位置移动并转移到另一个?,或任何其他替代解决方案?

【问题讨论】:

  • 你在使用 AutoLayout 吗?

标签: iphone objective-c xcode drag-and-drop


【解决方案1】:

UIGestureRecognizer 被 Apple 推荐用于最近的 iOS。您不仅可以将它用于 UIButton,还可以用于 UIView(尤其是在您的情况下为 UIImageView)等。所以我想推荐它。

在界面中:

@interface TestDragViewController : UIViewController {
    IBOutlet UIImageView *dragImage;
    CGPoint originalCenter;
}

在 viewDidLoad 中,请记得启用 userInteraction:

- (void)viewDidLoad {
    [super viewDidLoad];


    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self 
                                                                                 action:@selector(dragGesture:)];
    [dragImage addGestureRecognizer:panGesture];
    [dragImage setUserInteractionEnabled:YES];
}

在它的选择器中,我只是设置了动画来可视化返回效果:

#pragma mark -
#pragma mark UIPanGestureRecognizer selector
- (void) dragGesture:(UIPanGestureRecognizer *) panGesture{
    CGPoint translation = [panGesture translationInView:self.view];

    switch (panGesture.state) {
        case UIGestureRecognizerStateBegan:{
            originalCenter = dragImage.center;
        }
            break;
        case UIGestureRecognizerStateChanged:{
            dragImage.center = CGPointMake(dragImage.center.x + translation.x,
                                           dragImage.center.y + translation.y);
        }
            break;
        case UIGestureRecognizerStateEnded:{            
            [UIView animateWithDuration:kImageReturnTime 
                             animations:^{
                                 dragImage.center = originalCenter;
                             }
                             completion:^(BOOL finished){
                                 NSLog(@"Returned");
                             }];
        }
            break;
        default:
            break;
    }

    [panGesture setTranslation:CGPointZero inView:self.view];
}

干杯,

汤米

【讨论】:

  • 到目前为止,这是正确的解决方案,没有复杂性或创建不必要的抽象!干得好,Tommy!
  • 如果我使用 AutoLayout 会不会弄得一团糟?
【解决方案2】:

全局定义 CGPoint,或在 .h 文件中。

  CGPoint point;          

      UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
      [button addTarget:self action:@selector(imageTouch:withEvent:)forControlEvents:UIControlEventTouchDown];
      [button addTarget:self action:@selector(imageMoved:withEvent:) forControlEvents:UIControlEventTouchDragInside];
      [button setImage:[UIImage imageNamed:@"vehicle.png"] forState:UIControlStateNormal];
      [self.view addSubview:button];

后来我定义:

- (IBAction) imageMoved:(UIButton*) sender withEvent:(UIEvent *) event
 {
point = [[[event allTouches] anyObject] locationInView:self.view];
UIControl *control = sender;
control.center = point;
 [sender addTarget:self action:@selector(touches:withEvent:) forControlEvents:UIControlEventTouchUpInside];
}

-(void)touches:(UIButton *)button withEvent:(UIEvent *)event {

[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction animations:^{
     button.center = point;

 } completion:^(BOOL finished){
     if (finished) {
    // do anything yu want
   }

效果很棒,因为我在我的项目中使用它!

【讨论】:

    【解决方案3】:

    如何在 UIControlEventTouchUpInside 上调用选择器,然后在选择器中,只需将按钮的框架设置为新的 x 和 y 坐标(您保存的坐标)。

    【讨论】:

    • 谢谢。但这会立即将 UIButton 移动到新位置,对吗?如果是这样,一旦调用 UIControlEventTouchUpInside 上的选择器,是否可以命令 UIButton 从当前位置移动到新位置?
    【解决方案4】:

    在我在您所指的线程中链接到的解决方案中,我创建了一个通用拖放管理器,该管理器负责将拖动的对象返回到原始位置(如果在已知拖放区之外释放)。目前解决方案中没有动画,但您可以结合上面提出的一些想法。

    看看generic drag and drop solution in iOS的一些方法

    【讨论】:

      【解决方案5】:

      你知道吗,我昨天刚在做这个,所以这里有一点额外的动画:

      - (void)previewImageTouchUpInside:(UIButton*)aButton {
          if (!previewImageDragged) {
              [self selectPreviewImage:aButton];
              return;
      }
      
          previewImageDragged = NO;
      
          // If user drag photo a little and then release, we'll still treat it as a tap
          //  instead of drag
          if ((originalPositionOfButton.x - aButton.center.x) * 
            (originalPositionOfButton.x - aButton.center.x) + 
            (originalPositionOfButton.y - aButton.center.y) * 
            (originalPositionOfButton.y - aButton.center.y) < 10) {
              aButton.center = originalPositionOfButton;
              [self selectPreviewImage:aButton];
              return;
          }
      
          [UIView animateWithDuration:0.5
              delay:0
              options:UIViewAnimationOptionCurveEaseOut |
              UIViewAnimationOptionAllowUserInteraction animations:^{
              aButton.center = originalPositionOfButton;
          } completion:nil];
      }
      
      
      
      - (void)previewImageDraggedInside:(UIButton*)aButton event:(UIEvent*)event {
          if (!previewImageDragged) {
              originalPositionOfButton = aButton.center;
              [self.view bringSubviewToFront:aButton];
              [self.view bringSubviewToFront:[self.view viewWithTag:CHOOSE_PHOTO_BUTTON_TAG]];
          }
      
          UITouch* touch = [[event allTouches] anyObject];
      
          previewImageDragged = YES;
          aButton.center = CGPointMake(aButton.center.x+[touch locationInView:self.view].x-
              [touch previousLocationInView:self.view].x, 
              aButton.center.y+[touch locationInView:self.view].y-
              [touch previousLocationInView:self.view].y);
      }
      

      它仍然有一些神奇的数字,我没有重命名函数和变量以适合您的示例,但应该很清楚。我在这里也做了缩进,因为我没有在我的代码中手动打断长行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-24
        • 1970-01-01
        • 2018-08-29
        相关资源
        最近更新 更多