【发布时间】:2011-06-10 02:54:44
【问题描述】:
我想要一个视图,其中有车辆在周围行驶,用户也可以拖放。你认为最好的大规模战略是什么?最好是从代表车辆的视图中还是从更大的视图中获取触摸事件?是否有您满意的用于拖放的简单范例?不同策略的缺点是什么?
【问题讨论】:
标签: iphone ipad ios drag-and-drop touch
我想要一个视图,其中有车辆在周围行驶,用户也可以拖放。你认为最好的大规模战略是什么?最好是从代表车辆的视图中还是从更大的视图中获取触摸事件?是否有您满意的用于拖放的简单范例?不同策略的缺点是什么?
【问题讨论】:
标签: iphone ipad ios drag-and-drop touch
假设您有一个带有背景图像的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;
}
与管理整个场景相比,单个车辆处理自己的阻力要容易得多。
【讨论】:
除了 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;
}
我并不是说这是答案的完美解决方案。尽管如此,我发现这是最简单的拖动解决方案。
【讨论】:
我有一个案例,我想在多个其他 uiview 之间拖放 uiview。在这种情况下,我找到了在包含所有拖放区和所有拖动山墙对象的超级视图中跟踪平移事件的最佳解决方案。未将事件侦听器添加到实际拖动视图的主要原因是,一旦我更改了拖动视图的超级视图,我就会丢失正在进行的平移事件。
相反,我实现了一个相当通用的拖放解决方案,可用于单个或多个拖放区。
我创建了一个简单的例子,可以在这里看到:Drag an drop uiviews between multiple other uiviews
如果您决定采用其他方式,请尝试使用 uicontrol 而不是 uibutton。它们声明 addTarget 方法并且更容易扩展 - 因此提供自定义状态和行为。
【讨论】:
我实际上会在车辆视图本身而不是大视图上跟踪拖动 - 除非有特殊原因不这样做。
在一种情况下,我允许用户通过在屏幕上拖动项目来放置项目。 在这种情况下,我尝试让 top view 和 child view 都可拖动。如果您向 UIView 添加一些“可拖动”视图并处理如何拖动它们,我发现它的代码更简洁。我对父 UIView 使用了一个简单的回调来检查新位置是否合适 - 所以我可以用动画来指示。
我猜顶视图轨道拖动也不错,但是如果您想添加仍与用户交互的不可拖动视图(例如按钮),这会稍微麻烦一些.
【讨论】:
-(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 的回答对我来说效果很好。如果您需要 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
}
【讨论】:
【讨论】:
对于 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")
}
添加查看结果☝️
【讨论】: