Usted dice que su imagen es 2048 de ancho y su vista es 1024 de ancho. No sé si esto significa que ha duplicado el contenido de una imagen de 1024 de ancho para hacer una imagen de 2048 de ancho.
De todos modos, esto es lo que sugiero. Vamos a tener que almacenar la capa de nubes y su animación en las variables de instancia:
@implementation ViewController {
CALayer *cloudLayer;
CABasicAnimation *cloudLayerAnimation;
}
En lugar de establecer el contenido de la capa de nubes a la imagen de la nube, establecimos su color de fondo a un color de trama creada a partir de la imagen. De esta manera, podemos establecer límites de la capa a lo que queramos y la imagen será de baldosas para llenar los límites:
-(void)cloudScroll {
UIImage *cloudsImage = [UIImage imageNamed:@"TitleClouds.png"];
UIColor *cloudPattern = [UIColor colorWithPatternImage:cloudsImage];
cloudLayer = [CALayer layer];
cloudLayer.backgroundColor = cloudPattern.CGColor;
Sin embargo, el sistema de coordenadas de un CALayer pone el origen en la esquina inferior izquierda en lugar de la parte superior izquierda, con el eje Y aumentando hacia arriba. Esto significa que el patrón se dibujará al revés. Podemos arreglar esto por voltear el eje Y:
cloudLayer.transform = CATransform3DMakeScale(1, -1, 1);
Por defecto, punto de anclaje de una capa está en su centro. Esto significa que establecer la posición de la capa establece la posición de su centro. Será más fácil posicionar la capa al establecer la posición de su esquina superior izquierda. Podemos hacer esto mediante el movimiento de su punto de anclaje a su esquina superior izquierda:
cloudLayer.anchorPoint = CGPointMake(0, 1);
La anchura de la capa debe ser el ancho de la imagen, más la anchura de la vista que contiene. De esta forma, a medida que desplazamos la capa para que se vea el borde derecho de la imagen, se dibujará otra copia de la imagen a la derecha de la primera copia.
CGSize viewSize = self.cloudsImageView.bounds.size;
cloudLayer.frame = CGRectMake(0, 0, cloudsImage.size.width + viewSize.width, viewSize.height);
Ahora estamos listos para añadir la capa a la vista:
[self.cloudsImageView.layer addSublayer:cloudLayer];
Ahora vamos a configurar la animación. Recuerde que hemos cambiado el punto de anclaje de la capa, por lo que podemos controlar su posición estableciendo la posición de su esquina superior izquierda. Queremos esquina superior izquierda de la capa para iniciar en la esquina superior izquierda de la vista:
CGPoint startPoint = CGPointZero;
y queremos esquina superior izquierda de la capa a moverse a la izquierda por el ancho de la imagen:
CGPoint endPoint = CGPointMake(-cloudsImage.size.width, 0);
El resto de la configuración de animación es la misma que su código.He cambiado la duración de 3 segundos para la prueba:
cloudLayerAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
cloudLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
cloudLayerAnimation.fromValue = [NSValue valueWithCGPoint:startPoint];
cloudLayerAnimation.toValue = [NSValue valueWithCGPoint:endPoint];
cloudLayerAnimation.repeatCount = HUGE_VALF;
cloudLayerAnimation.duration = 3.0;
Vamos a llamar a otro método para fijar realmente la animación a la capa:
[self applyCloudLayerAnimation];
}
Aquí está el método que aplica la animación:
- (void)applyCloudLayerAnimation {
[cloudLayer addAnimation:cloudLayerAnimation forKey:@"position"];
}
Cuando la aplicación entra en segundo plano (porque el usuario cambió a otra aplicación), el sistema elimina la animación de la capa de la nube. Entonces tenemos que volver a conectarlo cuando volvamos a entrar en primer plano. Es por eso que tenemos el método applyCloudLayerAnimation
. Necesitamos llamar a ese método cuando la aplicación entra en primer plano.
En viewDidAppear:
, podemos empezar a observar la notificación que nos dice que la aplicación ha entrado en el primer plano:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
Tenemos que dejar de observar la notificación cuando nuestro punto de vista desaparece, o cuando se cancela la asignación del controlador de vista:
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
}
Cuando el controlador de vista realmente recibe la notificación, tenemos que aplicar de nuevo la animación:
- (void)applicationWillEnterForeground:(NSNotification *)note {
[self applyCloudLayerAnimation];
}
Aquí es todo el código juntos para copiar y pegar fácil:
- (void)viewDidLoad {
[self cloudScroll];
[super viewDidLoad];
}
-(void)cloudScroll {
UIImage *cloudsImage = [UIImage imageNamed:@"TitleClouds.png"];
UIColor *cloudPattern = [UIColor colorWithPatternImage:cloudsImage];
cloudLayer = [CALayer layer];
cloudLayer.backgroundColor = cloudPattern.CGColor;
cloudLayer.transform = CATransform3DMakeScale(1, -1, 1);
cloudLayer.anchorPoint = CGPointMake(0, 1);
CGSize viewSize = self.cloudsImageView.bounds.size;
cloudLayer.frame = CGRectMake(0, 0, cloudsImage.size.width + viewSize.width, viewSize.height);
[self.cloudsImageView.layer addSublayer:cloudLayer];
CGPoint startPoint = CGPointZero;
CGPoint endPoint = CGPointMake(-cloudsImage.size.width, 0);
cloudLayerAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
cloudLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
cloudLayerAnimation.fromValue = [NSValue valueWithCGPoint:startPoint];
cloudLayerAnimation.toValue = [NSValue valueWithCGPoint:endPoint];
cloudLayerAnimation.repeatCount = HUGE_VALF;
cloudLayerAnimation.duration = 3.0;
[self applyCloudLayerAnimation];
}
- (void)applyCloudLayerAnimation {
[cloudLayer addAnimation:cloudLayerAnimation forKey:@"position"];
}
- (void)viewDidUnload {
[self setCloudsImageView:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
}
- (void)applicationWillEnterForeground:(NSNotification *)note {
[self applyCloudLayerAnimation];
}
Cómo hacer que este ciclo continúe después de regresar del fondo (Minimizar la aplicación) ?? – Mutawe