我希望有一个视图,其中有车辆行驶,用户也可以拖放。您认为这样做的最佳大规模战略是什么?是否最好从代表车辆的视图或更大的视图中获取触摸事件?有没有一个简单的范例,你用来拖放你满意吗?不同策略的缺点是什么?
答案 0 :(得分:126)
假设您有一个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;
}
与管理整个场景相比,单个车辆处理自己的拖车要容易得多。
答案 1 :(得分:34)
除了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;
}
我不说,这是答案的完美解决方案。尽管如此,我发现这是最容易拖动的解决方案。
答案 2 :(得分:2)
我有一个案例,我想在多个其他uiviews之间拖放uiviews。在那种情况下,我找到了在包含所有拖放区域和所有拖动山墙对象的超级视图中跟踪平移事件的最佳解决方案。不将事件侦听器添加到实际拖动视图的主要原因是,一旦我更改了拖动视图的superview,我就丢失了正在进行的pan事件。
相反,我实现了一个非常通用的拖放解决方案,可以在单个或多个放置区使用。
我创建了一个可以在这里看到的简单示例:Drag an drop uiviews between multiple other uiviews
如果您决定采用其他方式,请尝试使用uicontrol而不是uibutton。它们声明了addTarget方法,并且更容易扩展 - 因此可以提供自定义状态和行为。
答案 3 :(得分:1)
我实际上会跟踪拖动车辆视图本身,而不是大视图 - 除非有特殊原因没有。
在一种情况下,我允许用户通过在屏幕上拖动项目来放置项目。 在这种情况下,我尝试了可以拖动的顶视图和子视图。如果你向UIView添加一些“可拖动的”视图并处理它们如何被拖动,我发现它是更干净的代码。我使用了对父UIView的简单回调来检查新位置是否合适 - 所以我可以用动画来表示。
让顶视图跟踪拖动我认为是一样好,但是如果您想要添加仍然与用户交互的不可拖动视图(例如按钮),这会使它更加混乱
答案 4 :(得分:1)
-(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");
}
答案 5 :(得分:1)
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
}
答案 6 :(得分:0)
这是从iOS 11开始拖放的最佳方式:
答案 7 :(得分:0)
用于Swift 4简便方法。
步骤1: 将您的按钮从情节提要板连接到View Controller。并设置所有基本的自动布局约束
@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")
}
添加查看结果☝️