2010-10-22 7 views
29

Ich muss den Maßstab der Bildlaufansicht genau überwachen, damit ich die Elemente der Inhaltsansicht (eine Unteransicht, die mehrere CALayers verwaltet) gemäß dem animierten Zoom der Bildlaufansicht aktualisieren kann.In iOS 4.0, warum UIScrollView zoomToRect: animiert: triggert nicht die Delegierten scrollViewDidScroll oder scrollViewDidZoom während der Animation?

auf iOS 3.1, alles wie erwartet funktioniert, verwende ich zoomToRect: animated: und die scrollViewDidScroll: Nachricht des UIScrollViewDelegatewiederholt aufgerufen wird, während die Animation stattfindet, dass ich die subview Elemente aktualisieren entsprechend dem tatsächlichen Zoom.

Derselbe Code unter iOS 4.0 zeigt nicht das gleiche Verhalten. Wenn ich rufe zoomToRect: animated:, die Delegierten (scrollViewDidScroll: und scrollViewDidZoom) nur einmal aufgerufen, die desinchronized meine Unterelemente macht, bis die Animation beendet ist. Tatsächlich springen die Unterelemente sofort und werden dann von der Zoom-Animation erfasst, bis alles an der richtigen Stelle ist. Es ist, als würde die Animation die Änderungen an den Unteransichten nicht übernehmen CALayers.

Ich habe versucht, manuell mit Animationsblöcken animieren, aber die Situation ist die gleiche, keine progressiven Callback-Aufrufe. Ich habe auch versucht KVO, aber es ist mir nicht klar, wie ich in eine UIScrollView-gesteuerte Animation tippen würde.

Gibt es einen Workaround auf iOS 4, der es mir erlauben würde, den Skalierungswert auf meine Subviews zu schieben, da die UIScrollView-Skalierung animiert ist?

Antwort

-1

Ist es möglich, alle Unteransichten innerhalb eines Animationsblocks zu aktualisieren (oder begin/commitAnimation)? Etwas wie:

[self zoomToRect:zoomRect animated:YES]; 
[UIView animateWithDuration:1.0 
    animations:^ { 
     // change your subviews 
    } 
]; 
+0

Ich habe diesen Ansatz versucht, aber das Problem ist, dass ich auf den aktuellen Wert des Zoomlevel zugreifen muss, während die Zoom-Animation ausgeführt wird, die nicht verfügbar ist. – David

+0

Konnten Sie einen Timer einstellen, der mehrmals feuert, während die Zoomanimation läuft und Ihre Berechnungen dort vornimmt? – Pablo

-1

Register für KVO der zoomScale Eigenschaft des UIScrollView nach zoomToRect:animated: nennen.

[scrollView addObserver:self 
      forKeyPath:@"zoomScale" 
       options:(NSKeyValueObservingOptionNew | 
         NSKeyValueObservingOptionOld) 
       context:NULL]; 

Dann implementieren diese Methode:

- (void)observeValueForKeyPath:(NSString *)keyPath 
       ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 
{ 
    if ([keyPath isEqual:@"zoomScale"]) { 
    // use the new zoomScale value stored 
    // in the NSKeyValueChangeNewKey change 
    // dictionary key to resize your subviews 
    } 
    // be sure to call the super implementation 
    // if the superclass implements it 
    [super observeValueForKeyPath:keyPath 
       ofObject:object 
       change:change 
       context:context]; 
} 

Schauen Sie sich die KVO documentation.

+0

Ich stoße auf eine wirklich alte Antwort, aber ich kann das anscheinend nicht funktionieren lassen. Ich registriere mich selbst als Beobachter von scrollView für den Schlüsselpfad von @ "zoomScale", aber beobachteValueForKeyPath: ofObject: change: context: wird nie aufgerufen. –

+0

Adam Mika, warum benutzt du nicht scrollViewDidZoom aus dem UIScrollViewDelegate Protocol http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIScrollViewDelegate_Protocol/Reference/UIScrollViewDelegate.html (sein iOS 3.2+ obwohl) – Jonny

+2

Es ist eine lange Zeit, aber ich muss dies ablehnen, weil es nicht funktioniert. Der Parameter "observeValueForKeyPath" wird nie aufgerufen. Nicht wenn der Zoom endet oder wenn der Zoom auftritt. – David

1

In IOS 4.0 werden Animationen vom Betriebssystem ausgeführt - ich gehe davon aus, die GPU-basierte Hardwarebeschleunigung so weit wie möglich zu nutzen. Als Nachteil wird es schwieriger, Werte zu animieren, die von einem anderen (animierten) Wert abgeleitet sind. Wie in Ihrem Fall die Positionen der Teilansichten, die von der Zoomstufe des UIScrollView abhängen. Um dies zu ermöglichen, sollten Sie die Animation der Unteransichten so einstellen, dass sie parallel zur Animation des Zoomens verläuft. Versuchen Sie so etwas wie:

[UIView animateWithDuration:0.5 delay:0 
        options:UIViewAnimationOptionLayoutSubviews 
       animations:^{ 
    theScrollView.zoomScale = zoomScale; 
    // layout the subviews here 
} completion:^(BOOL finished) {}]; 

Dies sollte die Rahmeneigenschaften der Subviews aus dem gleichen Animation Kontext gesetzt, und deshalb sollten sie zusammen mit dem O animiert werden.

Siehe auch die Antworten auf diese Frage: How to make UIScrollView send scrollViewDidScroll messages during animations

8

Brutal aber funktioniert.

einige Eigenschaften definieren:

@property (nonatomic, strong) UIView *zoomedView;  
@property (nonatomic, strong) CADisplayLink *displayLink; 
@property (nonatomic) CGFloat currentScale; 

Inform UIScrollView die UIView gezoomt werden soll:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView 
{ 
    return self.zoomedView; 
} 

Register für ein CADisplayLink Zecken. Es läuft Core Animation als auch, so wird es auf denselben Intervallen gekickt:

self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTick)]; 
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 

prüfen zoomedView der presentationLayer für aktuelle Werte.

+0

Verbunden: http://stackoverflow.com/a/17123900/1464716 – fionbio