28 votes

Où déterminer la taille de UIView

Résumé : Comment le UIViewController doit-il connaître la taille de son instance UIView lors de l'initialisation de cette vue ?

La méthode d'initialisation dédiée à une UIView est la méthode initWithFrame :(CGRect)frame. Elle définit le cadre de la UIView nouvellement créée. Cette méthode peut être appelée à partir de la méthode loadView du UIViewController, si la vue de ce contrôleur d'affichage est demandée. La documentation de UIViewController indique ce qu'il faut faire en ce qui concerne le sous-classement et la taille de la vue :

Lorsque vous créez les vues de votre hiérarchie de vues vous devez toujours définir l'option propriétés de redimensionnement de vos vues. Lorsqu'un contrôleur de vues est affiché à l'écran l'écran, sa vue racine est généralement redimensionnée pour s'adapter à l'espace disponible, qui peut varier en fonction de l'orientation l'orientation actuelle de la fenêtre et de la présence d'autres éléments d'interface tels que la barre d'état.

Ainsi, l'instance UIViewController doit définir ces propriétés. Jusqu'ici tout va bien, le UIViewController n'a pas besoin de connaître la taille de sa vue.

Lorsque la vue d'un UIViewController est demandée et que la propriété view est nulle, la méthode loadView du contrôleur de vue est appelée. Il y a maintenant un problème, car l'UIView doit être initialisée, mais le contrôleur de vue ne sait toujours pas quelle doit être la taille de la vue. Quelle taille doit-on initialiser cette vue ? Où dans le code déterminez-vous la taille de la vue ?

Vous pourriez initialiser la vue avec un rectangle zéro (CGRectZero) :

- (void)loadView {
    self.view = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
}

Et laissez l'appelant définir le cadre de vue comme suit :

UIViewController *viewController = [[MyUIViewController alloc] init];
// next two lines are normally combined, but for clarity they are not now
UIView *view = viewController.view;
view.frame = CGRectMake(0, 0, 200, 200);

Celui-ci demande la vue au contrôleur de vue (viewController.view), et charge donc sa vue avec la méthode loadView. Cette méthode loadView initialise la vue avec un CGRectZero. Ensuite, l'appelant définit son cadre (view.frame = ...).

Le problème est que la propriété frame de la vue est définie deux fois, ce qui peut entraîner un double travail supplémentaire si votre UIView personnalisée effectue une mise en page avancée dans la méthode setFrame (placement et redimensionnement des sous-vues, par exemple). Vous pouvez éviter cela en créant une méthode d'initialisation dédiée pour le UIViewController qui demande déjà à l'appelant un CGRect, que vous stockez dans un ivar. Au moment où la méthode loadView est appelée, vous utilisez cet ivar pour créer la vue.

Quelle est la bonne façon de procéder ici ? Soit en définissant deux fois le cadre de la vue (en l'initialisant avec CGRectZero, et en le définissant ensuite), soit en donnant au UIViewController une nouvelle méthode d'initialisation avec un CGRect (et donc en lui donnant une propriété de cadre) ? Ou bien est-ce que je rate quelque chose et y a-t-il d'autres possibilités ?

8voto

Nikolai Ruhe Points 45433

Tu ne le fais pas. doivent utiliser l'initialisateur désigné. Utilisez simplement init comme dans [[UIView alloc] init] . L'initialisateur désigné doit être utilisé à partir des initialisateurs des sous-classes.

D'autre part, le fait de fixer le cadre deux fois ne devrait pas faire beaucoup de mal. L'exécution d'un grand nombre de tâches dans setFrame: est inhabituel. La mise en page est normalement effectuée en layoutSubviews et n'est effectué qu'une seule fois.

0voto

Ben G Points 2106

J'essaie actuellement d'accomplir la même chose après avoir sous-classé UIViewController pour créer un composant générique et j'ai remarqué quelque chose d'assez bizarre :

UIViewController possède une méthode "loadView" que vous pouvez surcharger pour (en citant la documentation) "C'est ici que les sous-classes doivent créer leur hiérarchie de vues personnalisée".

Je crée donc ma hiérarchie de vues, en composant mon écran à l'aide d'une taille de cadre par défaut (puisque je ne sais pas forcément dans quel cadre je dois afficher les choses au moment où loadView est appelé).

Mais alors, sur quel appel dois-je régler correctement la taille des cadres ? Aka : à quel moment mon contrôleur de vue est-il conscient de la taille réelle de sa vue ?

Dois-je créer un "setFrame" dans ma sous-classe ViewController que l'objet créant le viewcontroller doit appeler ? cela semble bizarre.

drvdijk : avez-vous trouvé une solution à votre problème ?

EDIT : je viens de trouver cette note dans la documentation de UIViewController : Note : Vous ne devriez pas utiliser les contrôleurs de vues pour gérer des vues qui ne remplissent qu'une partie de leur fenêtre, c'est-à-dire une partie seulement de la zone définie par le rectangle de contenu de l'application. Si vous voulez avoir une interface composée de plusieurs vues plus petites, intégrez-les toutes dans une seule vue racine et gérez cette vue avec votre contrôleur de vue.

Il semble donc que la vue principale de UIViewController soit toujours en plein écran. Point barre.

Cela me pose cependant un problème, car j'essaie de créer un UITabBarViewController personnalisé (pour pouvoir afficher des images personnalisées dans la barre d'onglets, et non un dégradé bleu) : mon tabBarViewController doit afficher les subviewcontrollers dans une partie de la fenêtre seulement...

0voto

Tafkadasoh Points 1958

Vous pouvez calculer les limites de l'espace disponible à l'écran (qui dépend de la présence d'autres vues comme la barre de navigation, la barre d'onglets et la barre d'état). Vous pouvez alors utiliser ces limites pour le paramètre frame de la fonction [[UIView alloc] initWithFrame:] dans loadView.

Si c'est ce que vous voulez, vous trouverez peut-être ma réponse ici utile : Déterminer la taille correcte dans loadView

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