sábado, 31 de agosto de 2013

Animación de imágenes en iOS

En iOS se pueden programar animaciones de imágenes de manera sencilla. Vamos a ver un ejemplo en el que dos UIImageView intercambian sus posiciones, deslizándose de una a otra, cuando el usuario toca una de ellas. Además veremos las diferencias de usar el sistema de springs y struts o Autolayout.

Primero vamos a crear los dos UIImageView en el storyboard, image1 e image2 y cablearemso hacía el código para crear las propiedades.



De esta forma en el interface tendremos algo así:


@interface AnimacionViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *image1;
@property (weak, nonatomic) IBOutlet UIImageView *image2;
@end

Desde el inspector de atributos a una la pondremos como Background amarillo y a la otra rojo para poder diferenciarlas. Hay que tener también en cuenta que se debe permitir la interacción del usuario, por lo que el check deberá estar marcado tal y como se ve en la siguiente figura.




Ahora añadiremos el reconocimiento de gestos. Como lo que queremos es que la animación se produzca al tocar las imágenes, necesitamos el UITapGestureRecognizer. Lo crearemos en el viewDidLoad y se lo añadimos a las dos imágenes.



- (void)viewDidLoad
{
    [super viewDidLoad];
    
UITapGestureRecognizer *tapGesture1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];

UITapGestureRecognizer *tapGesture2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap)];
    
    [self.image1 addGestureRecognizer:tapGesture1];
    [self.image2 addGestureRecognizer:tapGesture2];
}

Como veis, la acción que se va a ejecutar es tap, que todavía no hemos definido. En ella lo que vamos a hacer es ejecutar el mensaje interchangImageView:imageView1 withImageView:imageView2, que también tenemos que definir.


- (void)tap
{
    [self interchangImageView:self.image1
                withImageView:self.image2];
    
}


Y es en interchangImageView:imageView1 withImageView:imageView2 donde veremos la diferencia de usar Autolayout o no.

Sin Autolayout


- (void)interchangImageView:(UIImageView *)imageView1 withImageView:(UIImageView *)imageView2
{
    CGPoint image1CenterPoint = imageView1.center;
    CGPoint image2CenterPoint = imageView2.center;
    
    [UIView animateWithDuration:1.0 animations:^{
        imageView1.center = image2CenterPoint;
        imageView2.center = image1CenterPoint;
    }];
}

Vemos que simplemente obtenemos el centro de cada imagen y luego los intercambiamos utilizando el class method animateWithDuration:animations de UIView. La duración de la animación será un segundo y en en bloque animations es donde intercambiamos los centros de las imágenes.

Con Autolayout
El método anterior no funciona si autolayout está activado. Si se moverían las imágenes pero, debido a las constraint definidas, volverían a su posición original. Por eso la animación debe basarse en las constraints. 

Añadiremos las constraints necesarias a ambas imágenes. En este caso son Top Space, Leading Space, Width y Height.


Cablearemos las dos Vertical Space para crear las dos propiedades NSLayoutConstraint, con lo que el interface ahora deberá quedar así:


@interface AnimacionViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *image1;
@property (weak, nonatomic) IBOutlet UIImageView *image2;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *verticalConstraintImage1;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *verticalConstraintImage2;
@end


Y el interchangImageView:imageView1 withImageView:imageView2 en este caso lo crearemos así:


- (void)interchangImageView:(UIImageView *)imageView1 withImageView:(UIImageView *)imageView2
{
    CGFloat img1ConstraintConstant = self.verticalConstraintImage1.constant;
    CGFloat img2ConstraintConstant = self.verticalConstraintImage2.constant;
    
    self.verticalConstraintImage1.constant = img2ConstraintConstant;
    self.verticalConstraintImage2.constant = img1ConstraintConstant;
    
    [imageView1 setNeedsUpdateConstraints];
    [imageView2 setNeedsUpdateConstraints];
    
    [UIView animateWithDuration:1.0 animations:^{
        [imageView1 layoutIfNeeded];
        [imageView2 layoutIfNeeded];
    }];
}

Lo que conseguimos con esto es intercambiar la distancia de ambas al top layout, por eso una subirá y la otra bajará. Al haber cambiado las constraints de las imágenes, es necesario llamar al mensaje setNeedsUpdateConstraints. Y, en el animateWithDuration, llamamos a layoutIfNeeded.

@Fin


No hay comentarios:

Publicar un comentario