2010-09-05 5 views
6

Je souhaite mettre à jour manuellement le contentOffset d'un UIScrollView lors des changements de rotation. La vue de défilement remplit l'écran et a la largeur flexible et la taille flexible.contentOffset de UIScrollView pendant la rotation

J'essaie actuellement de mettre à jour le contentOffset dans willRotateToInterfaceOrientation, comme ceci:

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [Utils logPoint:myScrollView.contentOffset tag:@"initial"]; 
    myScrollView.contentOffset = CGPointMake(modifiedX, modifiedY); 
    [Utils logPoint:myScrollView.contentOffset tag:@"modified"]; 
} 

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 
    [Utils logPoint:myScrollView.contentOffset tag:@"final"]; 
} 

Cependant, la valeur finale n'est pas la valeur modifiée, et il semble un peu être influencé par elle, mais ce n'est pas évident pour moi comment.

Ce sont quelques-uns des résultats que je reçois:

initial: (146.000000;-266.000000) 
modified: (81.000000;-108.000000) 
final: (59.000000;-0.000000) 

initial: (146.000000;-266.000000) 
modified: (500.000000;500.000000) 
final: (59.000000;500.000000) 

initial: (146.000000;-266.000000) 
modified: (-500.000000;-500.000000) 
final: (-0.000000;-0.000000) 

Comment puis-je mettre à jour le contentOffset d'une vue de défilement lors d'un changement de rotation?

+1

Est-ce que vous essayez de changer la contentOffset dans 'willAnimateRotationToInterfaceOrientation' à la place? Un bloc d'animation devrait être en place d'ici là, peut-être que le résultat est différent. – Pascal

+0

@Pascal Oui, et ça marche bien. Je voudrais quand même savoir pourquoi il ne se comporte pas comme prévu si je le change dans willRotateToInterfaceOrientation. – hpique

+0

Ma conjecture serait que le cadre du parent ne change que ** après ** 'willRotateToInterfaceOrientation', donc vous définissez un différent contentOffset, mais celui-là est immédiatement changé car l'image de la super-vue change seulement alors. Pour le système d'exploitation, c'est comme si vous aviez changé le cadre quelque temps plus tôt, pas en ce qui concerne la rotation en attente. – Pascal

Répondre

12

Conversion mon commentaire à une réponse :)

Essayez de changer contentOffset à l'intérieur willAnimateRotationToInterfaceOrientation:duration: à la place. Un bloc d'animation devrait être en place d'ici là, et le système d'exploitation considère vos modifications à contentOffset comme appartenant aux changements causés par la rotation.

Si vous modifiez auparavant le paramètre contentOffset, il semble que le système ne respecte pas ces modifications comme appartenant à la rotation et applique toujours le redimensionnement à la rotation, cette fois à partir de vos nouvelles dimensions.

+0

A travaillé comme un charme, en ajoutant des extraits de code pour aider les autres. – Shardul

+1

cette méthode est obsolète. Essayez d'utiliser 'viewWillTransitionToSize' ou' willTransitionToTraitCollection' – Gerald

4

Les snippets suivants sont utiles lorsque la pagination est activée sur UIScrollView et que le décalage de page doit être conservé.

déclarer une propriété qui va calculer la position de currentPage avant la rotation, et le mettre à -1 dans viewDidLoad

@property (assign, nonatomic) NSInteger lastPageBeforeRotate; 

remplacer ensuite la méthode willRotateToInterfaceOrientation:toInterfaceOrientation:duration et attribuer la valeur calculée à elle.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    int pageWidth = self.scrollView.contentSize.width/self.images.count; 
    int scrolledX = self.scrollView.contentOffset.x; 
    self.lastPageBeforeRotate = 0; 

    if (pageWidth > 0) { 
     self.lastPageBeforeRotate = scrolledX/pageWidth; 
    } 

    [self showBackButton:NO]; 
} 

Ensuite, nous nous assurons que avant la rotation est effectuée, nous avons mis notre contenu scrollview compensé correctement, de manière à se concentrer à notre lastPageBeforeRotate

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
     if (self.lastPageBeforeRotate != -1) { 
      self.scrollView.contentOffset = CGPointMake(self.scrollView.bounds.size.width * self.lastPageBeforeRotate, 0); 
      self.lastPageBeforeRotate = -1; 
     } 
} 
+0

Merci beaucoup! C'est la seule solution qui a réellement fonctionné pour moi :) –

3

réponse Mise à jour pour iOS 8+

Mettre en oeuvre viewWillTransitionToSize: withTransitionCoordinator: dans votre contrôleur.

Exemple:

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { 
    NSUInteger visiblePage = (NSInteger) self.scrollView.contentOffset.x/self.scrollView.bounds.size.width; 

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) { 
     self.scrollView.contentOffset = CGPointMake(visiblePage * self.scrollView.bounds.size.width, self.scrollView.contentOffset.y); 
    } completion:nil]; 
} 
+0

Merci! Il est intéressant que scrollView.bounds utilise la nouvelle valeur/different dans la fonction animateAlongsideTransition. –

Questions connexes