28 votes

Pourquoi dois-je définir manuellement le cadre de ma vue dans viewDidLoad ?

J'ai une configuration assez basique avec un UINavigationController dans un UITabBarController. Je souhaite mettre en page de manière programmatique la vue du rootViewController de ce navcontroller, mais lorsque je regarde self.view.frame dans viewDidLoad, j'obtiens ceci (en anglais) paysage par exemple) :

1. view frame: {{20, 0}, {748, 1024}} // looks like an odd portrait mode

Puis je me dirige automatiquement vers Portrait, et j'obtiens ceci :

2. view frame: {{0, 0}, {768, 911}}

Ensuite, quand je retourne dans Paysage, le cadre est maintenant celui-ci :

3. view frame: {{0, 0}, {1024, 655}}

Et d'autres événements d'autorotation basculeront entre les valeurs de trame #2 et #3.

Pour contourner la bizarrerie du point 1, je fais actuellement ceci dans viewDidLoad :

if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
    self.view.frame = CGRectMake(0, 0, 768, 911);
} else {
    self.view.frame = CGRectMake(0, 0, 1024, 655);
}

J'ai l'impression de rater quelque chose ici. Pourquoi le cadre par défaut de la vue ne correspondrait-il pas au cadre lorsqu'elle revient par autorotation à la même orientation ? Le cadre de la vue n'est-il pas réglé sur l'orientation initiale ? Je suis très confus...

Je dois préciser qu'aucun des éléments ci-dessus, y compris mon hack bancal, ne change quoi que ce soit visuellement. La raison pour laquelle j'ai fait ce hack est que lorsque je disposerai mes sous-vues dans cette vue, elles seront basées sur l'endroit où je m'attends à ce qu'elles soient, c'est-à-dire le coin supérieur gauche juste sous la barre de navigation.

Qu'est-ce que je fais de mal ?

MISE À JOUR : désactiver toutes les fonctions de dimensionnement automatique de la vue modifie le résultat #1 :

view frame: {{0, 0}, {748, 1024}}

Cela semble un peu plus proche, mais ne correspond toujours pas au numéro 3.

90voto

cduhn Points 11229

Il n'est pas garanti que le cadre soit le même dans viewDidLoad que lors de l'affichage final de la vue. UIKit ajuste le cadre de la vue de votre contrôleur de vue avant de l'afficher, en fonction du contexte dans lequel elle apparaîtra. La taille est déterminée en fonction de l'orientation de l'interface et des dimensions de toute barre de navigation, barre d'onglets, barre d'outils ou barre d'état visible (qui a elle-même une hauteur qui peut changer, par exemple lorsque vous êtes en communication téléphonique).

Il permet de comprendre ce qui se passe lorsque la vue d'un contrôleur de vue est chargée et affichée :

  1. Quelque chose accède à votre contrôleur de vue view pour la première fois. Cela peut se produire dans votre propre code, ou dans UIKit en réponse à une action de l'utilisateur comme la sélection d'un onglet.

  2. UIKit charge paresseusement la vue de votre contrôleur d'affichage en appelant loadView si elle est définie, ou en chargeant la vue à partir de la NIB qui a été spécifiée dans initWithNibName:bundle: . Si aucun des deux n'existe, UIKit charge simplement une vue vide.

  3. Appels UIKit viewDidLoad une fois que la vue et ses sous-vues ont été entièrement chargées. À ce stade, le cadre de la vue sera celui qui a été défini dans le NIB, ou dans le fichier loadView .

  4. Un appel à UIKit pour afficher la vue de votre contrôleur de vue. Encore une fois, il peut s'agir d'une action de l'utilisateur, comme taper sur un onglet, ou d'un appel de méthode explicite dans votre code comme pushViewController:animated: o presentModalViewController:animated: .

  5. UIKit redimensionne la vue en fonction du contexte dans lequel elle sera présentée, comme décrit ci-dessus.

  6. Appels UIKit viewWillAppear: . Le cadre doit maintenant avoir la taille qui sera affichée. ( ?) EDIT : Ceci n'est peut-être plus vrai. Voir les commentaires ci-dessous.

  7. UIKit affiche la vue, avec ou sans animations.

  8. Appels UIKit viewDidAppear: .

Comme vous pouvez le voir, si vous avez besoin de connaître la taille du cadre de votre vue avant qu'elle ne soit présentée, viewWillAppear: est votre seule et unique opportunité. N'oubliez pas que cette taille peut changer après l'apparition de la vue pour diverses raisons, notamment des événements de rotation ou des modifications de la hauteur de la barre d'état. C'est pourquoi il est important de donner à chaque vue secondaire un masque de redimensionnement automatique approprié, afin de garantir que la mise en page puisse s'adapter correctement à tout changement de limites.

Si vous souhaitez construire votre hiérarchie de vues manuellement, l'endroit recommandé pour le faire est dans loadView. Puisque vous construisez vous-même la vue dans cette méthode, vous pouvez initialiser son cadre comme vous le souhaitez. La taille que vous choisissez n'a pas beaucoup d'importance, puisque UIKit est susceptible de la modifier de toute façon. Veillez simplement à définir vos autoresizingMasks de manière appropriée.

-7voto

Dimple panchal Points 265

Il y aura une méthode dans votre classe

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations    return YES; }

Mettez votre cadre dans cette méthode... Alors ça marchera bien.

Par exemple :

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{
        // Return YES for supported orientations    
        if(interfaceOrientation == UIDeviceOrientationPortrait || UIDeviceOrientationPortraitUpsideDown)
                self.view.frame = CGRectMake(0, 0, FRAME.WIDTHinPOTRAIT, FRAME.HEIGHTinPOTRAIT);
        else if(interfaceOrientation == UIDeviceOrientationLandscapeRight || UIDeviceOrientationLandscapeLeft)
                self.view.frame = CGRectMake(0, 0, FRAME.WIDTHinLANDSCAPE, FRAME.HEIGHTinLANDSCAPE);

        return YES; 
}

FRAME.WIDTH > largeur souhaitée FRAME.HEIGHT > hauteur souhaitée

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