2010-07-11 5 views
7

J'ai un exemple très simple UIScrollView qui ne fait tout simplement pas ce qu'il est censé faire. Je ne sais pas si c'est un bogue avec l'API ou un bogue dans mon code. Fondamentalement, j'ai un UIViewController avec UIScrollView comme c'est la vue. Lorsque je l'ajoute au UIWindow et que je change l'orientation de l'iPad, je me déconnecte de la taille UIScrollView, qui est incorrecte (?).UIScrollView ne pas obtenir la nouvelle taille sur l'orientation changement

Voici mon UIViewController mise en œuvre:

@implementation CustomViewController 
- (void)loadView { 
    scrollView = [[[UIScrollView alloc] init] autorelease]; 
    scrollView.delegate = self; 
    scrollView.backgroundColor = [UIColor redColor]; 
    self.view = scrollView; 
} 

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    CGSize rect = scrollView.frame.size; 
    NSLog(@"will rotate w%f h%f", rect.width, rect.height); 
} 

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    CGSize rect = scrollView.frame.size; 
    NSLog(@"will animate rotation w%f h%f", rect.width, rect.height); 
} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 
    CGSize rect = scrollView.frame.size; 
    NSLog(@"did rotate w%f h%f", rect.width, rect.height); 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return YES; 
} 

@end 

Quand je lance le code ci-dessus, je vois les entrées suivantes dans la console:

2010-07-11 11:03:05.214 Untitled2[6682:207] will rotate w768.000000 h1004.000000 
2010-07-11 11:03:05.214 Untitled2[6682:207] will animate rotation w748.000000 h1024.000000 
2010-07-11 11:03:05.619 Untitled2[6682:207] did rotate w748.000000 h1024.000000 
2010-07-11 11:03:07.951 Untitled2[6682:207] will rotate w748.000000 h1024.000000 
2010-07-11 11:03:07.958 Untitled2[6682:207] will animate rotation w768.000000 h1004.000000 
2010-07-11 11:03:08.367 Untitled2[6682:207] did rotate w768.000000 h1004.000000 

Comme vous pouvez le voir, les changements d'orientation ne redimensionne la UIScrollView , mais seulement pour permettre la nouvelle barre d'état. Je m'attendrais à ce que la largeur et la hauteur changent radicalement, car le UIScrollView est plus large que haut et vice versa.

Existe-t-il un moyen d'obtenir le UIScrollView pour signaler sa taille réelle?

Répondre

3

J'ai la réponse si vous êtes toujours à la recherche. Testez les limites , pas le cadre.

Raison: le cadre est une propriété dérivée des bornes et la transformation est appliquée pour la rotation.

+0

Cela ne fonctionne pas. J'intercepte un changement, puis j'utilise NSStringFromRect (self.bounds) et il imprime les limites "juste avant de changer". Mais l'orientation currentDevice renvoie la valeur correcte. Au moins, celui-ci revient constamment la même chose correctement, mais l'homme ... ce problème ne devrait pas prendre autant de temps. A partir des docs, alors que les bornes sont les non-dérivées, n'est-ce pas toujours 0,0, même largeur de cadre, même hauteur de cadre? –

+0

L'origine des limites est toujours 0,0 par défaut sauf si vous modifiez la partie de vue que vous souhaitez afficher. Ce n'est que la moitié de l'histoire, un CGRect contient aussi un membre de taille et c'est ce qui change habituellement lorsque vous redimensionnez, réorienter une vue. Les fonctions "volonté" ci-dessus vous donnent les "valeurs avant", les fonctions "faites" vous donnent les "valeurs après". –

2

Les vues ne se redimensionneront pas automatiquement si leurs super-vues sont redimensionnées, sauf si vous les définissez spécifiquement. Pour cette vue de défilement, vous devez lui indiquer de redimensionner sa largeur et sa hauteur lorsque sa vue d'ensemble le fait.

scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 
+0

Malheureusement, après l'ajout d'un masque de redimensionnement je reçois toujours les dimensions invalides qui reviennent. Visuellement, tout va bien, mais je ne peux pas compter sur les dimensions du cadre. Je l'ai piraté en détectant l'orientation des périphériques et en inversant la largeur et la hauteur en mode paysage - ce n'est pas idéal, mais ça marche. – d2kagw

+0

Vous devez tester l'orientation [[UIDevice currentDevice]] et voir ceci: UIDeviceOrienationIsPortrait() ou similaire pour le tester. Le cadre sera erroné, mais il indiquera la bonne orientation. C'est agaçant, je m'en occupe tout de suite, mais je suis content que quelque chose soit solide. Peut-être que la réponse aux limites va m'aider à auto-dimensionner mon UIScrollView, mais le mien est offkilter même après avoir manuellement changé les maths pour correspondre à l'orientation –

1

J'ai remarqué que la détermination de la nouvelle contentSize dans didRotateFromInterfaceOrientation est également impossible si vous commencez avec un fichier iPhone NIB au lieu d'un dédié fichier iPad NIB: les images du fichier iPhone NIB sont beaucoup plus petits et donc la la hauteur calculée du contenu devient beaucoup plus grande qu'elle ne devrait l'être lorsque vous êtes sur un iPad. Apple DID dit que je DOIT créer un fichier NIB iPad distinct ...

Donc, je reçois aussi les anciennes dimensions dans didRotateFromInterfaceOrientation, mais pour moi c'est maintenant moins un problème, puisque iOS gère tout OK une fois que je Commencez avec le bon fichier NIB. Pourtant, il me semble moins intuitif que dans la méthode didRotateFromInterfaceOrientation les dimensions du cadre sont incorrectes pour la vue actuelle.

PS. J'ai trouvé une solution à la fin, il suffit d'utiliser les notifications au lieu de didRotateFromInterfaceOrientation.

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(orientationChanged:) 
               name:UIDeviceOrientationDidChangeNotification 
               object:nil]; 

Puis, dans la méthode orientationChanged, réglez les vues sur les nouveaux cadres. J'ai eu un dernier problème: si l'orientation initiale était différente de l'orientation de la pointe, la vue serait toujours fausse, j'ai résolu cela en créant un nouveau fichier NIB spécialement pour la vue paysage. Dans la méthode init, le ViewController choisit le NIB qu'il charge en fonction de l'orientation actuelle.

0

Je fixe généralement cela en définissant une valeur de contentSize à 0 comme CGSizeMake(contentSize.width, 0) pour la vue horizontale.

Pour forcer UIScrollView à défiler uniquement, par ex. valeur horizontale non-défilable pour contentSize à 0>CGSizeMake(contentSize.width, 0).

J'espère que ça aide.

0

Je ne sais pas ce qui vous aide parce que je jamais testé cela, mais je pense que ce pourrait être vous aider

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
self.view = scrollView; 
CGSize rect = scrollView.frame.size; 
NSLog(@"will rotate w%f h%f", rect.width, rect.height); 
} 

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
self.view = scrollView;  
CGSize rect = scrollView.frame.size; 
NSLog(@"will animate rotation w%f h%f", rect.width, rect.height); 
} 

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 
self.view = scrollView; 
CGSize rect = scrollView.frame.size; 
NSLog(@"did rotate w%f h%f", rect.width, rect.height); 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
return YES; 
} 
Questions connexes