【问题标题】:Basic Drag and Drop in iOSiOS中的基本拖放
【发布时间】:2011-06-10 02:54:44
【问题描述】:

我想要一个视图,其中有车辆在周围行驶,用户也可以拖放。你认为最好的大规模战略是什么?最好是从代表车辆的视图中还是从更大的视图中获取触摸事件?是否有您满意的用于拖放的简单范例?不同策略的缺点是什么?

【问题讨论】:

标签: iphone ipad ios drag-and-drop touch


【解决方案1】:

假设您有一个带有背景图像的UIView 场景和许多vehicles,您可以将每个新车定义为UIButton(UIImageView 可能也可以使用):

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];

然后您可以通过响应UIControlEventTouchDragInside 事件将车辆移动到任何您想要的位置,例如:

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

与管理整个场景相比,单个车辆处理自己的阻力要容易得多。

【讨论】:

  • 看起来很棒而且非常简单!我会试试这个。
  • 如果用户拖动按钮的速度快于动画更新速度,此策略是否会导致拖动中断?如果他们的手指伸出盒子,它将停止接收 imageMoved:withEvent: 调用,对吗?
  • 如何知道图像是否停止拖动?你怎么知道手指移开了?
  • ohho - 是否可以偏移图像或按钮的拖动“手柄”,以便可以拖动右上角或左上角?
  • 当我尝试获取异常时--[drag_move_textViewController imageTouch:withEvent:]: unrecognized selector sent to instance 0x4b4b1c0
【解决方案2】:

除了 ohho 的回答之外,我还尝试了类似的实现,但没有“快速”拖动和居中拖动的问题。

按钮初始化是……

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

及方法实现:

- (IBAction) imageMoved:(id) sender withEvent:(UIEvent *) event
{
    UIControl *control = sender;

    UITouch *t = [[event allTouches] anyObject];
    CGPoint pPrev = [t previousLocationInView:control];
    CGPoint p = [t locationInView:control];

    CGPoint center = control.center;
    center.x += p.x - pPrev.x;
    center.y += p.y - pPrev.y;
    control.center = center;
}

我并不是说这是答案的完美解决方案。尽管如此,我发现这是最简单的拖动解决方案。

【讨论】:

  • 在您的示例代码中,您在 UIControl *control=sender 使用后定义它 - 不应该更早定义吗?
  • @PeterJohnson:事实上在这种情况下它并不重要。自从你提到的那一行以来,这个变量就没有更早的用法了:)
  • CGPoint pPrev = [t previousLocationInView:control] 怎么样? CGPoint p = [t locationInView:control];这两行似乎都指的是“控制”?
  • 天哪!我怎么能错过呢? :-O ...我已经编辑了答案。
  • 我添加了按钮表单界面构建器,并使用自动布局进行一些登录
【解决方案3】:

我有一个案例,我想在多个其他 uiview 之间拖放 uiview。在这种情况下,我找到了在包含所有拖放区和所有拖动山墙对象的超级视图中跟踪平移事件的最佳解决方案。未将事件侦听器添加到实际拖动视图的主要原因是,一旦我更改了拖动视图的超级视图,我就会丢失正在进行的平移事件。

相反,我实现了一个相当通用的拖放解决方案,可用于单个或多个拖放区。

我创建了一个简单的例子,可以在这里看到:Drag an drop uiviews between multiple other uiviews

如果您决定采用其他方式,请尝试使用 uicontrol 而不是 uibutton。它们声明 addTarget 方法并且更容易扩展 - 因此提供自定义状态和行为。

【讨论】:

    【解决方案4】:

    我实际上会在车辆视图本身而不是大视图上跟踪拖动 - 除非有特殊原因不这样做。

    在一种情况下,我允许用户通过在屏幕上拖动项目来放置项目。 在这种情况下,我尝试让 top viewchild view 都可拖动。如果您向 UIView 添加一些“可拖动”视图并处理如何拖动它们,我发现它的代码更简洁。我对父 UIView 使用了一个简单的回调来检查新位置是否合适 - 所以我可以用动画来指示。

    我猜顶视图轨道拖动也不错,但是如果您想添加仍与用户交互的不可拖动视图(例如按钮),这会稍微麻烦一些.

    【讨论】:

      【解决方案5】:
      -(void)funcAddGesture
      { 
      
       // DRAG BUTTON
              UIPanGestureRecognizer *panGestureRecognizer;
              panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(dragButton:)];
              panGestureRecognizer.cancelsTouchesInView = YES;
      
              UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
              button.frame = CGRectMake(50, 100, 60, 60);
              [button addTarget:self action:@selector(buttontapEvent) forControlEvents:UIControlEventPrimaryActionTriggered];
              [button setImage:[UIImage imageNamed:@"button_normal.png"] forState:UIControlStateNormal];
              [button addGestureRecognizer:panGestureRecognizer];
              [self.view addSubview:button];
      }
      
      
      - (void)dragButton:(UIPanGestureRecognizer *)recognizer {
      
          UIButton *button = (UIButton *)recognizer.view;
          CGPoint translation = [recognizer translationInView:button];
      
          float xPosition = button.center.x;
          float yPosition = button.center.y;
          float buttonCenter = button.frame.size.height/2;
      
          if (xPosition < buttonCenter)
              xPosition = buttonCenter;
          else if (xPosition > self.view.frame.size.width - buttonCenter)
              xPosition = self.view.frame.size.width - buttonCenter;
      
          if (yPosition < buttonCenter)
              yPosition = buttonCenter;
          else if (yPosition > self.view.frame.size.height - buttonCenter)
              yPosition = self.view.frame.size.height - buttonCenter;
      
          button.center = CGPointMake(xPosition + translation.x, yPosition + translation.y);
          [recognizer setTranslation:CGPointZero inView:button];
      }
      
      
      - (void)buttontapEvent {
      
          NSLog(@"buttontapEvent");
      }
      

      【讨论】:

        【解决方案6】:

        ohho 的回答对我来说效果很好。如果您需要 swift 2.x 版本:

        override func viewDidLoad() {
        
            let myButton = UIButton(type: .Custom)
            myButton.setImage(UIImage(named: "vehicle"), forState: .Normal)
        
            // drag support
            myButton.addTarget(self, action:#selector(imageMoved(_:event:)), forControlEvents:.TouchDragInside)
            myButton.addTarget(self, action:#selector(imageMoved(_:event:)), forControlEvents:.TouchDragOutside)
        }
        
        private func imageMoved(sender: AnyObject, event: UIEvent) {
            guard let control = sender as? UIControl else { return }
            guard let touches = event.allTouches() else { return }
            guard let touch = touches.first else { return }
        
            let prev = touch.previousLocationInView(control)
            let p = touch.locationInView(control)
            var center = control.center
            center.x += p.x - prev.x
            center.y += p.y - prev.y
            control.center = center
        }
        

        【讨论】:

          【解决方案7】:

          【讨论】:

            【解决方案8】:

            对于 Swift 4 简单而简单的方法。 ?

            第 1 步: 将您的按钮从 Storyboard 连接到视图控制器。并设置所有基本的自动布局约束

             @IBOutlet weak var cameraButton: UIButton!
            

            第 2 步:viewDidLoad()

            中为您的按钮添加平移手势
            self.cameraButton.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGestureHandler(panGesture:))))
            

            第 3 步:

            添加 panGestureHandler

            @objc func panGestureHandler(panGesture recognizer: UIPanGestureRecognizer) {
            
                     let location = recognizer.location(in: view)
                    cameraButton.center = location
            
                }
            

            现在是您的按钮操作

            @IBAction func ButtonAction(_ sender: Any) {
            
                    print("This is button Action")
                }
            

            添加查看结果☝️

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-03-23
              • 2012-01-18
              • 1970-01-01
              • 1970-01-01
              • 2013-02-04
              • 2018-02-06
              相关资源
              最近更新 更多