2011-02-13 21 views
27

¿Es posible arrastrar UIView por la pantalla de iOS mientras tiene imágenes y texto? p.ej. tarjetas pequeñas ¿Podría señalarme el tema similar (resuelto)? No he encontrado ninguno.UIView arrastre (imagen y texto)

Respuesta

33

Mientras que UIView no tiene un soporte integrado para moverse a lo largo del usuario arrastrando, no debería ser tan difícil implementarlo. Es aún más fácil cuando solo se trata de arrastrar en la vista, y no de otras acciones como tocar, tocar dos veces, tocar varias veces, etc.

Lo primero que debe hacer es crear una vista personalizada, digamos DraggableView, por subclassing UIView. Luego, anule el método touchesMoved:withEvent: de UIView, y puede obtener una ubicación de arrastre actual allí, y mover el DraggableView. mira el siguiente ejemplo.

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *aTouch = [touches anyObject]; 
    CGPoint location = [aTouch locationInView:self.superview]; 
    [UIView beginAnimations:@"Dragging A DraggableView" context:nil]; 
    self.frame = CGRectMake(location.x, location.y, 
          self.frame.size.width, self.frame.size.height); 
    [UIView commitAnimations]; 
} 

Y porque todas las subvistas del objeto DraggableView se moverán también. Así que ponga todas sus imágenes y textos como subvistas del objeto DraggableView.

Lo que implementé aquí es muy simple. Sin embargo, si desea comportamientos más complejos para el arrastre (por ejemplo, el usuario tiene que tocar la vista durante unos segundos para mover la vista), tendrá que anular otros métodos de manejo de eventos (touchesBegan: withEvent: y touchesEnd: withEvent) también.

24

Además de MHC's answer.

Si no desea que la esquina superior izquierda de la vista para saltar bajo el dedo, también puede anular touchesBegan así:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UITouch *aTouch = [touches anyObject]; 

    offset = [aTouch locationInView: self]; 
} 

y cambiar touchesMoved de MHC a:

-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
     UITouch *aTouch = [touches anyObject]; 
     CGPoint location = [aTouch locationInView:self.superview]; 

     [UIView beginAnimations:@"Dragging A DraggableView" context:nil]; 
     self.frame = CGRectMake(location.x-offset.x, location.y-offset.y, 
           self.frame.size.width, self.frame.size.height); 
     [UIView commitAnimations]; 
    } 

también debe definir CGPoint offset en la interfaz:

@interface DraggableView : UIView 
{ 
    CGPoint offset; 
} 

EDIT:

Arie Litovsky proporciona una solución más elegante que le permite deshacerse de la Ivar: https://stackoverflow.com/a/10378382/653513

5

A pesar de que la solución rokjarc funciona, usando

CGPoint previousLocation = [aTouch previousLocationInView:self.superview]; 

evita la CGPoint offset creación y el llame al touchesBegan:withEvent:

+0

uno de los buenos. Pero debes usarlo como lo sugiere diablosnuevos, con 'CGRectOffset'. –

+0

Agradable, no requiere punto de contacto –

36

Esto es una buena solución, basada en pepouze ' s respuesta, se vería como (probado, ¡funciona!)

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    UITouch *aTouch = [touches anyObject]; 
    CGPoint location = [aTouch locationInView:self]; 
    CGPoint previousLocation = [aTouch previousLocationInView:self]; 
    self.frame = CGRectOffset(self.frame, (location.x - previousLocation.x), (location.y - previousLocation.y)); 
} 
+0

Este código hace que UIVIew ** not ** salte bajo su dedo, bien hecho. –

2

Aquí es una solución para arrastrar a custom UIView (que se puede escalar o rotar a través de su transform), que puede contener imágenes y/o texto (sólo editar el Tile.xib según sea necesario):

app screenshot

- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event 
{ 
    UITouch *touch = [touches anyObject]; 
    CGPoint location = [touch locationInView:self]; 
    CGPoint previous = [touch previousLocationInView:self]; 

    if (!CGAffineTransformIsIdentity(self.transform)) { 
     location = CGPointApplyAffineTransform(location, self.transform); 
     previous = CGPointApplyAffineTransform(previous, self.transform); 
    } 

    self.frame = CGRectOffset(self.frame, 
           (location.x - previous.x), 
           (location.y - previous.y)); 
} 
0

Esto funciona para mí.Mi UIView girar y escalar

- (void) touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ 

UITouch *touch = [touches anyObject]; 
CGPoint location = [touch locationInView:self]; 
CGPoint previous = [touch previousLocationInView:self]; 

if (!CGAffineTransformIsIdentity(self.transform)) { 
    location = CGPointApplyAffineTransform(location, self.transform); 
    previous = CGPointApplyAffineTransform(previous, self.transform); 
} 
CGRect newFrame = CGRectOffset(self.frame, 
           (location.x - previous.x), 
           (location.y - previous.y)); 
float x = CGRectGetMidX(newFrame); 
float y = CGRectGetMidY(newFrame); 
self.center = CGPointMake(x, y); 

}