2010-10-22 5 views
29

Je dois surveiller de près l'échelle de la vue déroulante pour pouvoir mettre à jour les éléments de la vue de contenu (sous-vue gérant plusieurs CALayers) en fonction du zoom animé de la vue défilée.Dans iOS 4.0, pourquoi UIScrollView zoomToRect: animé: ne déclenche pas les délégués scrollViewDidScroll ou scrollViewDidZoom lors de l'animation?

Sur iOS 3.1, tout fonctionne comme prévu, j'utilise zoomToRect: animation: et scrollViewDidScroll: message du UIScrollViewDelegateest appelée à plusieurs reprises tandis que l'animation se déroule, me laisser mettre à jour les éléments de sous-vue selon le zoom réel.

Le même code sur iOS 4.0 n'exhibe pas le même comportement. Quand j'appelle zoomToRect: animé:, les délégués (scrollViewDidScroll: et scrollViewDidZoom) ne s'appelle une fois, ce qui rend mes éléments sous desinchronized jusqu'à ce que l'animation est terminée. En fait, les sous-éléments sautent immédiatement et sont ensuite rattrapés par l'animation zoom jusqu'à ce que tout soit à la bonne place. C'est comme si l'animation ne détectait pas les modifications sur les sous-vues CALayers.

J'ai essayé d'animer manuellement avec des blocs d'animation, mais la situation est la même, aucun appel de rappel progressif. J'ai aussi essayé le KVO, mais je ne vois pas comment j'utiliserais une animation gérée par UIScrollView.

Existe-t-il une solution de contournement sur iOS 4 qui me permettrait de pousser la valeur d'échelle à mes sous-vues comme l'échelle UIScrollView est animée?

Répondre

-1

Est-il viable de mettre à jour toutes les sous-vues dans un bloc d'animation (ou commencer/commitAnimation)? Quelque chose comme:

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

J'ai essayé cette approche, mais le problème est que j'ai besoin d'accéder à la valeur actuelle du niveau zoom pendant que l'animation zoomming est exécutée, ce qui n'est pas disponible. – David

+0

Pourriez-vous configurer une minuterie qui se déclenche plusieurs fois pendant que l'animation de zoom est en cours et y effectuer vos calculs? – Pablo

-1

Inscrivez-vous KVO de la propriété zoomScale du UIScrollView après que vous appelez zoomToRect:animated:.

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

Ensuite, mettre en œuvre cette méthode:

- (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]; 
} 

Vérifiez la KVO documentation.

+0

Cogner une réponse vraiment ancienne, mais je n'arrive pas à faire fonctionner cela du tout. Je m'inscris en tant qu'observateur de scrollView pour le chemin clé de @ "zoomScale", mais observeValueForKeyPath: ofObject: change: context: ne se fait jamais appeler. –

+0

Adam Mika, pourquoi n'utilisez-vous pas le scrollViewDidZoom du protocole UIScrollViewDelegate http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIScrollViewDelegate_Protocol/Reference/UIScrollViewDelegate.html (son iOS 3.2+ cependant – Jonny

+2

Cela fait longtemps, mais j'ai besoin de downvote parce que ça ne marche pas. Le paramètre observeValueForKeyPath n'est jamais appelé. Pas à la fin du zoom ni pendant le zoom. – David

1

Dans IOS 4.0, les animations sont effectuées par le système d'exploitation - je suppose utiliser au maximum l'accélération matérielle basée sur le GPU. Comme inconvénient, il devient plus difficile d'animer une valeur dérivée d'une autre valeur (animée). Comme dans votre cas, les positions des sous-vues dépendent du niveau de zoom de l'UIScrollView. Pour que cela se produise, vous devez configurer l'animation des sous-vues pour aller en parallèle avec l'animation du zoom. Essayez quelque chose comme:

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

Cela devrait définir les propriétés du cadre des sous-vues à l'intérieur du même contexte d'animation, et par conséquent, ils doivent être animés ensemble par le système d'exploitation.

Voir aussi les réponses à cette question: How to make UIScrollView send scrollViewDidScroll messages during animations

8

Brutal mais fonctionne.

Définir des propriétés:

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

Inform UIScrollView qui UIView va être zoomée:

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

Inscrivez-vous pour un CADisplayLink tiques. Il fonctionne Core Animation aussi bien, il sera lancé le même intervalle:

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

presentationLayer de Check zoomedView pour les valeurs actuelles.

- (void)displayLinkTick 
{ 
    CALayer *zoomedLayer = self.zoomedView.layer.presentationLayer; 
    CGFloat scale = zoomedLayer.transform.m11; 

    if (scale != self.currentScale) { 
     self.currentScale = scale; // update property 

     // the scale has changed! 
    } 
} 
+0

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

Questions connexes