iphone ipad ios drag-and-drop touch

iphone - Arrastrar y soltar básico en iOS



ipad drag-and-drop (7)

Quiero tener una vista en la que haya vehículos circulando que el usuario también pueda arrastrar y soltar. ¿Cuál crees que es la mejor estrategia a gran escala para hacer esto? ¿Es mejor obtener eventos táctiles de las vistas que representan los vehículos o desde una vista más amplia? ¿Hay algún paradigma simple que hayas utilizado para arrastrar y soltar con el que estés satisfecho? ¿Cuáles son los inconvenientes de las diferentes estrategias?


Además de la respuesta de ohho, he intentado una implementación similar, pero sin problemas de arrastre "rápido" y centrado para arrastrar.

La inicialización del botón es ...

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

y la implementación del método:

- (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; }

No digo, que esta es la solución perfecta para la respuesta. Sin embargo, encontré esta la solución más fácil para arrastrar.


De hecho, me gustaría rastrear arrastrando en la vista del vehículo en sí, en lugar de la gran vista, a menos que haya una razón particular para no hacerlo.

En un caso en el que permití al usuario colocar elementos arrastrándolos en la pantalla. En ese caso, experimenté tanto con la vista superior como con las vistas secundarias arrastrables. Descubrí que es un código más limpio si agrega algunas vistas "arrastrables" al UIView y maneja cómo podrían ser arrastradas. Utilicé una devolución de llamada simple al UIView padre para verificar si la nueva ubicación era adecuada o no, así que pude indicar con animaciones.

Supongo que tener la pista de vista superior arrastrándose es tan buena, pero eso hace que sea un poco más complicado si quieres agregar vistas no arrastrables que aún interactúan con el usuario, como un botón.



La respuesta de Ohho funcionó bien para mí. En caso de que necesite la versión rápida 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 }


Tuve un caso en el que me gustaría arrastrar / colocar uiviews entre varias otras vistas. En ese caso, encontré la mejor solución para rastrear los eventos de panoramización en una súper vista que contiene todas las zonas de colocación y todos los objetos de aguilón de arrastre. La razón principal para NO agregar los detectores de eventos a las vistas reales arrastradas fue que perdí los eventos pan en curso tan pronto como cambié la supervista para la vista arrastrada.

En su lugar, implementé una solución genérica de arrastrar y soltar que se podía usar en una o varias zonas de colocación.

He creado un ejemplo simple que se puede ver aquí: Arrastrar una uiviews de caída entre varias otras uiviews

Si decide ir por el otro lado, intente usar uicontrol en lugar de uibutton. Declaran los métodos addTarget y son mucho más fáciles de extender, por lo tanto, proporcionan un estado y comportamiento personalizados.


Supongamos que tiene una escena UIView con una imagen de fondo y muchos vehicles , puede definir cada vehículo nuevo como un UIButton (UIImageView también funcionará probablemente):

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

Luego puede mover el vehículo donde lo desee, respondiendo al evento UIControlEventTouchDragInside , por ejemplo:

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

Es mucho más fácil para un vehículo individual manejar sus propias cargas, comparándolo para administrar la escena como un todo.


-(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"); }