28 votes

Dans iOS 4.0, pourquoi UIScrollView zoomToRect: animated: ne déclenche-t-il pas les délégués scrollViewDidScroll ou scrollViewDidZoom pendant l'animation?

J'ai besoin de surveiller étroitement l'échelle de défilement de la vue, de sorte que je puisse mettre à jour le contenu de la vue des éléments (une sous-vue de gérer plusieurs CALayers) selon le défilement de l'affichage d'animation de zoom.

Sur iOS 3.1, tout fonctionne comme prévu, j'utilise zoomToRect:animation: et la scrollViewDidScroll: message de la UIScrollViewDelegate est appelée à plusieurs reprises alors que l'animation a lieu, pour me permettre de mettre à jour les éléments sous-vue à zoom.

Le même code sur iOS 4.0 ne prend pas en exibit le même comportement. Quand je l'appelle zoomToRect:animation:les délégués (scrollViewDidScroll: et scrollViewDidZoom) uniquement être appelé pour une fois, ce qui rend mes sous-éléments desinchronized jusqu'à ce que l'animation est terminée. En fait, les sous-éléments de sauter immédiatement et de vous faire attraper par le zoom de l'animation jusqu'à ce que tout est à la bonne place. C'est comme si l'animation n'est pas de ramasser les modifications sur les sous-vues CALayers.

J'ai essayé d'animer manuellement avec l'animation des blocs, mais la situation est la même, pas de progressif rappel des appels. J'ai également essayé le KVO, mais il n'est pas clair pour moi comment je pourrais puiser dans une UIScrollView géré l'animation.

Est-il une solution sur iOS 4 qui me permettrait de pousser la valeur de l'échelle de mon sous-vues comme le UIScrollView échelle est animé?

9voto

Brutal mais fonctionne.

Définissez quelques propriétés:

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

Informez UIScrollView qui UIView va être zoomé:

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

Inscrivez-vous pour un CADisplayLink ticks. Il exécute également Core Animation, il sera donc lancé aux mêmes intervalles:

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

Vérifiez presentationLayer de 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!
    }
}
 

1voto

fishinear Points 2452

Dans IOS 4.0, les animations sont réalisées par le système d'exploitation - je suppose que de faire usage de la base de GPU d'accélération matérielle autant que possible. Comme un inconvénient de cela, il devient plus difficile d'animer une des valeurs qui est dérivée à partir d'un autre (animés) de la valeur. Comme dans votre cas, les positions des sous-vues qui dépendent du niveau de zoom de la UIScrollView. Afin de faire que cela se produise, vous devez configurer l'animation de la sous-vues d'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 de la sous-vues de l'intérieur de la même animation contexte, et par conséquent, ils doivent être animés conjointement par l'OS.

Voir aussi les réponses à cette question: Comment faire UIScrollView envoyer scrollViewDidScroll messages lors des animations

-1voto

Binyamin Bauman Points 447

Inscrivez-vous au KVO de la propriété zoomScale de UIScrollView après avoir appelé zoomToRect:animated: .

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

Ensuite, implémentez 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];
}
 

Consultez la documentation KVO.

-1voto

Pablo Points 363

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X