Iphone iOS中的基本拖放操作

Iphone iOS中的基本拖放操作,iphone,ipad,ios,drag-and-drop,touch,Iphone,Ipad,Ios,Drag And Drop,Touch,我想有一个视图,其中有车辆行驶,用户也可以拖放。你认为这样做的最佳大规模战略是什么?最好是从代表车辆的视图中获取触摸事件,还是从更大的视图中获取触摸事件?有没有一个简单的拖放范例让你满意?不同策略的缺点是什么?我实际上会在车辆视图本身上跟踪拖动,而不是在大视图上跟踪拖动,除非有特别的理由不这样做 在一种情况下,我允许用户通过在屏幕上拖动项目来放置项目。 在这种情况下,我尝试了让俯视图和子视图都可以拖动。我发现,如果在UIView中添加几个“可拖动”视图,并处理如何拖动它们,代码会更简洁。我对父U

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

我实际上会在车辆视图本身上跟踪拖动,而不是在大视图上跟踪拖动,除非有特别的理由不这样做

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


我想拖动俯视轨迹也不错,但如果您想添加仍与用户交互的不可拖动视图(如按钮),则会稍微有点混乱。

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

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

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

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

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

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

我创建了一个简单的示例,可以在这里看到:


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

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

按钮初始化为

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;
}
我不是说,这是一个完美的答案。尽管如此,我发现这是最简单的拖动解决方案。

-(void)funcadd
-(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");
}
{ //拖动按钮 UIPanGestureRecognizer*panGestureRecognizer; panGestureRecognizer=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(拖动按钮:)]; pangestrerecognizer.cancelsTouchesInView=YES; UIButton*button=[UIButton button类型:UIButtonTypeCustom]; button.frame=CGRectMake(50,100,60,60); [按钮添加目标:自操作:@selector(ButtontAppEvent)for ControlEvents:UIControlEventPrimaryActionTriggered]; [按钮设置图像:[UIImage ImageName:@“button_normal.png”]用于状态:UIControlStateNormal]; [按钮添加GestureRecognitor:PangestureRecognitor]; [self.view addSubview:按钮]; } -(无效)拖动按钮:(UIPangestureRecognitor*)识别器{ UIButton*按钮=(UIButton*)识别器.view; CGPoint translation=[识别器translationView:按钮]; float xPosition=button.center.x; 浮动y位置=按钮。中心。y; 浮动按钮中心=button.frame.size.height/2; 如果(X位置<按钮中心) xPosition=按钮中心; else if(xPosition>self.view.frame.size.width-buttonCenter) xPosition=self.view.frame.size.width-buttonCenter; 如果(位置<按钮中心) Y位置=按钮中心; else if(位置>self.view.frame.size.height-按钮中心) yPosition=self.view.frame.size.height-按钮中心; button.center=CGPointMake(xPosition+translation.x,yPosition+translation.y); [识别器setTranslation:CGPointZero查看:按钮]; } -(无效)按钮排气口{ NSLog(“按钮事件”); }
Oho的回答对我来说很有效。如果您需要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
}

以下是从iOS 11开始进行拖放的最佳方式:


为Swift 4提供了简便易行的方法。看起来很棒而且很简单!我将尝试一下。如果用户拖动按钮的速度快于动画更新的速度,此策略是否会导致拖动中断?如果他们的手指伸出盒子,它将停止接收图像移动:withEvent:调用,对吗?你怎么知道图像是否停止拖动?您如何知道手指已移出?ohho-是否可以偏移图像或按钮的拖动“手柄”,以便可以通过右上角或左上角拖动它?当我尝试获取异常时--[drag_move_textViewController imageTouch:withEvent:]:在示例代码中,无法识别的选择器发送到实例0x4B4B1C0,您在使用后定义UIControl*控件=发送方-不应该更早定义吗?@PeterJohnson:事实上,在这种情况下这并不重要。自从您提到的那一行之后,这个变量就没有更早的用法了:)那么CGPoint pPrev=[t previousLocationInView:control]呢;CGP点=[t位置视图:对照];前面这两行似乎都是指“控制”?哦,天哪!我怎么会错过呢-O。。。我已经编辑了答案。我添加了按钮表单界面生成器,我使用autolayout进行了一些登录。我确实隐藏了按钮,然后再次显示,当我这样做时,它会返回到原始位置。如何防止这种情况发生
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
}