在iOS中的基本拖放
我想有一个观点,其中有车辆左右,用户也可以拖放。 你认为最好的大规模战略是什么? 从代表车辆的视angular,还是从更大的angular度来看触摸事件是最好的? 你有一个简单的范例,你用拖放,你满意吗? 什么是不同的策略的弊端?
假设你有一个背景图像和许多vehicles
的UIView
场景,你可以定义每个新车作为一个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; }
个别车辆处理自己的拖拉比整个场景pipe理要容易得多。
除了ohho的回答,我已经尝试了类似的实现,但没有“快速”拖动和居中拖动的问题。
button的初始化是…
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 += px - pPrev.x; center.y += py - pPrev.y; control.center = center; }
我不这么说,这是答案的完美解决scheme。 不过,我发现这是最简单的拖动解决scheme。
我有一个情况,我想在其他多个uiviews之间拖放uiviews。 在这种情况下,我find了最好的解决scheme来跟踪包含所有拖放区域和所有拖动山墙对象的超级视图中的泛事件。 不把事件监听器添加到实际拖动视图的主要原因是,只要我更改了拖动视图的超级视图,就丢失了正在进行的泛事件。
相反,我实现了一个相当通用的拖放解决scheme,可以在单个或多个拖放区域上使用。
我已经创build了一个简单的例子,可以在这里看到: 拖放uiviews多个其他uiviews之间
如果您决定采用其他方式,请尝试使用uicontrol,而不是使用uibutton。 他们声明了addTarget方法,并且更容易扩展 – 从而给出自定义的状态和行为。
我实际上会追踪拖拽车辆视图本身,而不是大视野 – 除非有特别的理由否定。
在一种情况下,我允许用户通过拖放他们在屏幕上的项目。 在这种情况下,我尝试了顶视图和子视图可拖动。 我发现它是更干净的代码,如果你添加一些“可拖动”的意见的UIView和处理如何可以被拖动。 我用一个简单的callback父UIView来检查新的位置是否合适 – 所以我可以用animation表示。
如果您想添加仍然与用户交互的不可拖动的视图(例如button),那么拖拽顶部视图轨迹的效果会更好。
-(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"); }
ohho的回答对我来说效果不错。 如果您需要快速的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 += px - prev.x center.y += py - prev.y control.center = center }