Mówisz, że twój obraz ma 2048 szerokości, a twój widok ma 1024 szerokości. Nie wiem, czy oznacza to, że powielono zawartość obrazu o szerokości 1024 cm, aby uzyskać obraz o szerokości 2048 cm.
W każdym razie, oto co proponuję. Musimy zapamiętać warstwę chmur i jego animacji w zmiennych instancji:
@implementation ViewController {
CALayer *cloudLayer;
CABasicAnimation *cloudLayerAnimation;
}
Zamiast ustawiać jego zawartości warstwy chmur jest do chmury obrazu, możemy ustawić jego kolor tła na kolor wzoru utworzonego z obrazka. W ten sposób możemy ustawić granice warstwy, aby cokolwiek chcemy i obraz zostanie wyłożone do wypełnienia granic:
-(void)cloudScroll {
UIImage *cloudsImage = [UIImage imageNamed:@"TitleClouds.png"];
UIColor *cloudPattern = [UIColor colorWithPatternImage:cloudsImage];
cloudLayer = [CALayer layer];
cloudLayer.backgroundColor = cloudPattern.CGColor;
Jednak układ współrzędnych danego CALayer stawia pochodzenie w lewym dolnym zamiast górnym rogu przy zwiększaniu się osi Y. Oznacza to, że wzór zostanie odwrócony do góry nogami. Możemy to naprawić, odwracając oś Y:
cloudLayer.transform = CATransform3DMakeScale(1, -1, 1);
Domyślnie punkt kontrolny warstwy znajduje się w jej środku. Oznacza to, że ustawienie położenia warstwy ustawia położenie jej środka. Łatwiej będzie ustawić warstwę, ustawiając jej górny lewy róg. Możemy to zrobić poprzez przeniesienie jego punktu zaczepienia jej lewym górnym rogu:
cloudLayer.anchorPoint = CGPointMake(0, 1);
Szerokość warstwy musi być szerokość obrazu plus szerokość widoku zawierającego. W ten sposób, gdy przewijamy warstwę tak, aby widoczna była prawą krawędź obrazu, kolejna kopia obrazu zostanie narysowana po prawej stronie pierwszej kopii.
CGSize viewSize = self.cloudsImageView.bounds.size;
cloudLayer.frame = CGRectMake(0, 0, cloudsImage.size.width + viewSize.width, viewSize.height);
Teraz jesteśmy gotowi, aby dodać warstwę do widoku:
[self.cloudsImageView.layer addSublayer:cloudLayer];
Teraz skonfigurować animację. Pamiętaj, że zmieniliśmy punkt zakotwiczenia warstwy, dzięki czemu możemy kontrolować jego położenie, ustawiając pozycję jego lewego górnego rogu. Chcemy lewym górnym rogu warstwy, aby rozpocząć w widoku w lewym górnym rogu:
CGPoint startPoint = CGPointZero;
i chcemy lewym górnym rogu warstwy, aby przejść w lewo przez szerokość obrazka:
CGPoint endPoint = CGPointMake(-cloudsImage.size.width, 0);
Reszta konfiguracji animacji jest taka sama, jak kod.Zmieniłem czas trwania do 3 sekund do testowania:
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;
Będziemy wywołać inną metodę rzeczywiście załączyć animację do warstwy:
[self applyCloudLayerAnimation];
}
Oto metoda, która ma zastosowanie animacji:
- (void)applyCloudLayerAnimation {
[cloudLayer addAnimation:cloudLayerAnimation forKey:@"position"];
}
Gdy aplikacja wchodzi w tło (ponieważ użytkownik przełączył się na inną aplikację), system usuwa animację z warstwy chmury. Musimy więc ponownie go podłączyć, gdy ponownie wejdziemy na pierwszy plan. Dlatego mamy metodę applyCloudLayerAnimation
. Musimy wywołać tę metodę, gdy aplikacja wejdzie na pierwszy plan.
W viewDidAppear:
, możemy rozpocząć obserwację powiadomienie, że mówi nam aplikacja wprowadził nową wiedzę:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
Musimy przestać obserwując powiadomienie, gdy nasz pogląd znika, lub gdy kontroler widoku jest zwalniane:
- (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];
}
Kiedy kontroler widok rzeczywiście otrzymał zawiadomienie, musimy ponownie zastosować animację:
- (void)applicationWillEnterForeground:(NSNotification *)note {
[self applyCloudLayerAnimation];
}
Oto cały kod razem do łatwego kopiowania i wklejania:
- (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];
}
Jak aby ta pętla była kontynuowana po powrocie z tła (Zminimalizowanie aplikacji)? – Mutawe