2009-05-17 6 views
13

HINWEIS: Ich habe meine neue Lösung bei der UPDATE-Antwort unten hinzugefügt.Einblenden/Ausblenden Der Inhalt von UIScrollView wie Mobile Safari funktioniert in der Registerkarte

Ich versuche, die Effekte, die wir in Mobile Safari Registerkarte auf dem iPhone/iPod touch gesehen haben, neu zu erstellen.

Grundsätzlich ist es ein UIScrollView, das 4 wiederverwendbare UIView (wie Ringpuffer) hält und horizontal scrollt. Beim Scrollen wird die Deckkraft des UIView nahtlos mit dem Offset ein- und ausgeblendet.

Derzeit mache ich alle schmutzigen Job in - (void)scrollViewDidScroll:(UIScrollView *)scrollView. B. das containOffset von UIScrollView abrufen, die Seitenaufteilung bestimmen, das Delta zwischen contentOffset und jeder UIView-Position berechnen und den Alpha-Wert jeder UIView zum Zeitpunkt des Aufrufs von scrollViewDidScroll: festlegen/festlegen.

Und es funktioniert, Leistung ist in Ordnung, alles läuft reibungslos, aber das einzige Problem ist zu viel Berechnung.

Ich versuchte UIView die beginAnimations: und commitAnimations:, aber es ist nutzlos in scrollViewDidScroll:, da 1) der neuen Alpha-Wert noch von mir selbst berechnen müssen werden, und 2) scrollViewDidScroll: genannt gehalten beim Scrollen, es sinnlos ist hier die Animation zu tun. Gibt es eine Möglichkeit, diesen Teil mit Core Animation neu zu schreiben? Ich muss also nicht selbst den Alpha-Wert jeder UIView berechnen, stattdessen kann ich ganze Arbeiten Core Animation überlassen.

Antwort

26

UPDATE

ich mit einer anderen Art und Weise kam um den Alpha-Wert jeder Seite zu aktualisieren. Wenn die Inhaltsansicht erstellen, verwende ich KVO addObserver mit UIScrollView des Content:

[self.scrollView addObserver:[self.contentViews objectAtIndex:i] 
        forKeyPath:@"contentOffset" 
        options:NSKeyValueObservingOptionNew 
        context:@selector(updateAlpha:)]; 

So, dass jeder meiner contentViews die Nachricht erhalten, wenn Content geändert:

- (void)observeValueForKeyPath:(NSString *)keyPath 
         ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context { 
    [self performSelector:(SEL)context withObject:change]; 
} 

Und mein contentViews kann die Berechnung tun und selbst animieren beim Scrollen:

- (void)updateAlpha:(NSDictionary *)change { 
    CGFloat offset = [[change objectForKey:NSKeyValueChangeNewKey] CGPointValue].x; 
    CGFloat origin = [self frame].origin.x; 
    CGFloat delta = fabs(origin - offset); 

    [UIView beginAnimations:@"Fading" context:nil]; 
    if (delta < [self frame].size.width) { 
     self.alpha = 1 - delta/self.frame.size.width*0.7; 
    } else { 
     self.alpha = 0.3; 
    } 
    [UIView commitAnimations]; 
} 

natürlich müssen Sie den Beobachter entfernen, wenn Sie den Inhalt Ansicht von Superview entfernen, und fügen Sie sie erneut hinzu, wenn eine neue Inhaltsansicht erstellt wurde.

Hoffe diese Hilfe für diejenigen, die das gleiche tun wollen.

+1

Ich finde es gerade jetzt, und es ist großartig - danke fürs Teilen! Ein Fehler: Das anfängliche Alpha ist nicht für die einzige Offscreen-Ansicht eingestellt. Ich nehme an, ich könnte updateAlpha: explizit nennen, aber vielleicht reicht es aus, am Anfang explizit contentOffset zu setzen. Gedanken? –

2

Wie Sie feststellen werden, wie oft scrollViewDidScroll: aufgerufen wird, feuert UIScrollView nicht einfach ab und vergisst einen Kernanimationsübergang: Es verschiebt die Grenzen manuell nach Berührungen, Beschleunigung usw. Es gibt keine direkte Möglichkeit zu ändern Dies.

Wenn Sie jedoch durch Scroll-Ereignisse überschwemmt wir Sie, könnten Sie einen Trick versuchen wie folgt aus:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView 
{ 
    NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970]; 
    if (timestamp - _savedTimestamp) < 0.1) 
     return; 
    _savedTimestamp = timestamp; 

    // do the rest of your work here 
} 

H

+0

hatfink, danke für die Idee. Obwohl es nicht perfekt ist, sparen Sie trotzdem etwas CPU-Power. – digdog