Si dice che l'immagine è larga 2048 e la vista è 1024 di larghezza. Non so se questo significa che hai duplicato il contenuto di un'immagine a 1024 di larghezza per creare un'immagine di 2048-larghezza.
In ogni caso, ecco cosa suggerisco. Avremo bisogno di memorizzare lo strato di nubi e la sua animazione in variabili di istanza:
@implementation ViewController {
CALayer *cloudLayer;
CABasicAnimation *cloudLayerAnimation;
}
Invece di impostare contenuto del livello cloud per l'immagine nuvola, impostiamo il colore di sfondo a un colore modello creato dall'immagine. In questo modo, siamo in grado di impostare limiti del livello di quello che vogliamo e l'immagine verrà piastrelle per riempire i limiti:
-(void)cloudScroll {
UIImage *cloudsImage = [UIImage imageNamed:@"TitleClouds.png"];
UIColor *cloudPattern = [UIColor colorWithPatternImage:cloudsImage];
cloudLayer = [CALayer layer];
cloudLayer.backgroundColor = cloudPattern.CGColor;
Tuttavia, il sistema di coordinate di un CALayer pone l'origine in basso a sinistra invece che in alto a sinistra, con l'asse Y crescente. Ciò significa che il modello sarà disegnato al rovescio. Possiamo risolvere che girando l'asse Y:
cloudLayer.transform = CATransform3DMakeScale(1, -1, 1);
Per impostazione predefinita, il punto di ancoraggio di un livello è al suo centro. Ciò significa che l'impostazione della posizione del livello imposta la posizione del suo centro. Sarà più semplice posizionare il livello impostando la posizione del suo angolo superiore sinistro. Possiamo farlo spostando il suo punto di ancoraggio per l'angolo superiore sinistro:
cloudLayer.anchorPoint = CGPointMake(0, 1);
La larghezza dello strato deve essere la larghezza dell'immagine più la larghezza della vista contenente. In questo modo, mentre scorriamo lo strato in modo che il bordo destro dell'immagine venga visualizzato, un'altra copia dell'immagine verrà disegnata a destra della prima copia.
CGSize viewSize = self.cloudsImageView.bounds.size;
cloudLayer.frame = CGRectMake(0, 0, cloudsImage.size.width + viewSize.width, viewSize.height);
Ora siamo pronti per aggiungere il layer alla vista:
[self.cloudsImageView.layer addSublayer:cloudLayer];
Ora diamo istituito l'animazione. Ricorda che abbiamo cambiato il punto di ancoraggio del livello, in modo che possiamo controllarne la posizione impostando la posizione del suo angolo superiore sinistro. Vogliamo nell'angolo in alto a sinistra del livello per iniziare a nell'angolo superiore sinistro della vista:
CGPoint startPoint = CGPointZero;
e vogliamo angolo superiore sinistro del livello per spostarsi a sinistra per la larghezza dell'immagine:
CGPoint endPoint = CGPointMake(-cloudsImage.size.width, 0);
Il resto del setup di animazione è lo stesso del tuo codice.Ho cambiato la durata di 3 secondi per il test:
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;
Chiameremo un altro metodo per attaccare in realtà l'animazione allo strato:
[self applyCloudLayerAnimation];
}
Ecco il metodo che si applica l'animazione:
- (void)applyCloudLayerAnimation {
[cloudLayer addAnimation:cloudLayerAnimation forKey:@"position"];
}
Quando l'applicazione passa in background (poiché l'utente passa a un'altra app), il sistema rimuove l'animazione dal livello cloud. Quindi dobbiamo riattaccarlo quando entriamo di nuovo in primo piano. Ecco perché abbiamo il metodo applyCloudLayerAnimation
. Dobbiamo chiamare questo metodo quando l'app passa in primo piano.
In viewDidAppear:
, possiamo iniziare osservando la notifica che ci dice l'applicazione è entrato in primo piano:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
Dobbiamo smettere di osservare la notifica quando la nostra visione scompare, o quando il controller della vista è deallocata:
- (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];
}
Quando il controller della vista in realtà riceve la notifica, abbiamo bisogno di applicare di nuovo l'animazione:
- (void)applicationWillEnterForeground:(NSNotification *)note {
[self applyCloudLayerAnimation];
}
Ecco tutto il codice per semplificarne la copia e incolla:
- (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];
}
Come fare in modo che questo ciclo continui dopo essere tornato dallo sfondo (minimizzare l'applicazione) ?? – Mutawe