Il semble que l'intention d'Apple soit de traiter les deux orientations de l'iPad de la même manière - mais comme un certain nombre d'entre nous le constatent, il existe des raisons de conception très légitimes de vouloir modifier la disposition de l'interface utilisateur pour iPad Portrait par rapport à iPad Landscape.
Malheureusement, le système d'exploitation actuel ne semble pas prendre en charge cette distinction ... ce qui signifie que nous sommes de retour à la manipulation des contraintes de mise en page automatique dans le code ou des solutions de contournement similaires pour atteindre ce que nous devrions idéalement pouvoir obtenir gratuitement en utilisant l'interface utilisateur adaptative. .
Pas une solution élégante.
N'existe-t-il pas un moyen d'exploiter la magie qu'Apple a déjà intégrée à IB et UIKit pour utiliser une classe de taille de notre choix pour une orientation donnée?
~
En réfléchissant au problème de manière plus générique, j'ai réalisé que les «classes de taille» sont simplement des moyens de traiter plusieurs mises en page stockées dans IB, afin qu'elles puissent être appelées au besoin au moment de l'exécution.
En fait, une «classe de taille» n'est en réalité qu'une paire de valeurs d'énumération. Depuis UIInterface.h:
typedef NS_ENUM(NSInteger, UIUserInterfaceSizeClass) {
UIUserInterfaceSizeClassUnspecified = 0,
UIUserInterfaceSizeClassCompact = 1,
UIUserInterfaceSizeClassRegular = 2,
} NS_ENUM_AVAILABLE_IOS(8_0);
Ainsi, indépendamment de ce qu'Apple a décidé de nommer ces différentes variantes, il ne s'agit fondamentalement que d'une paire d'entiers utilisés comme identifiant unique, pour distinguer une mise en page d'une autre, stockée dans IB.
Maintenant, en supposant que nous créons une mise en page alternative (en utilisant une classe de taille inutilisée) dans IB - par exemple, pour iPad Portrait ... existe-t-il un moyen pour que l'appareil utilise notre choix de classe de taille (disposition de l'interface utilisateur) au besoin au moment de l'exécution ?
Après avoir essayé plusieurs approches différentes (moins élégantes) du problème, j'ai soupçonné qu'il pourrait y avoir un moyen de remplacer la classe de taille par défaut par programme. Et il y a (dans UIViewController.h):
// Call to modify the trait collection for child view controllers.
- (void)setOverrideTraitCollection:(UITraitCollection *)collection forChildViewController:(UIViewController *)childViewController NS_AVAILABLE_IOS(8_0);
- (UITraitCollection *)overrideTraitCollectionForChildViewController:(UIViewController *)childViewController NS_AVAILABLE_IOS(8_0);
Ainsi, si vous pouvez empaqueter la hiérarchie de votre contrôleur de vue en tant que contrôleur de vue `` enfant '', et l'ajouter à un contrôleur de vue parent de niveau supérieur ... alors vous pouvez conditionnellement remplacer l'enfant en pensant qu'il s'agit d'une classe de taille différente de la classe par défaut. du système d'exploitation.
Voici un exemple d'implémentation qui fait cela, dans le contrôleur de vue 'parent':
@interface RDTraitCollectionOverrideViewController : UIViewController {
BOOL _willTransitionToPortrait;
UITraitCollection *_traitCollection_CompactRegular;
UITraitCollection *_traitCollection_AnyAny;
}
@end
@implementation RDTraitCollectionOverrideViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setUpReferenceSizeClasses];
}
- (void)setUpReferenceSizeClasses {
UITraitCollection *traitCollection_hCompact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];
UITraitCollection *traitCollection_vRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular];
_traitCollection_CompactRegular = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection_hCompact, traitCollection_vRegular]];
UITraitCollection *traitCollection_hAny = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassUnspecified];
UITraitCollection *traitCollection_vAny = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassUnspecified];
_traitCollection_AnyAny = [UITraitCollection traitCollectionWithTraitsFromCollections:@[traitCollection_hAny, traitCollection_vAny]];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
_willTransitionToPortrait = self.view.frame.size.height > self.view.frame.size.width;
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]
_willTransitionToPortrait = size.height > size.width;
}
-(UITraitCollection *)overrideTraitCollectionForChildViewController:(UIViewController *)childViewController {
UITraitCollection *traitCollectionForOverride = _willTransitionToPortrait ? _traitCollection_CompactRegular : _traitCollection_AnyAny;
return traitCollectionForOverride;
}
@end
En guise de démonstration rapide pour voir si cela fonctionnait, j'ai ajouté des étiquettes personnalisées spécifiquement aux versions `` Regular / Regular '' et `` Compact / Regular '' de la disposition du contrôleur enfant dans IB:
Et voici à quoi cela ressemble en cours d'exécution, lorsque l'iPad est dans les deux orientations:
Voila! Configurations de classe de taille personnalisée au moment de l'exécution.
Espérons qu'Apple rendra cela inutile dans la prochaine version du système d'exploitation. En attendant, cela peut être une approche plus élégante et évolutive que de jouer par programme avec les contraintes de mise en page automatique ou de faire d'autres manipulations dans le code.
~
EDIT (6/4/15): Veuillez garder à l'esprit que l'exemple de code ci-dessus est essentiellement une preuve de concept pour démontrer la technique. N'hésitez pas à vous adapter au besoin à votre propre application spécifique.
~
EDIT (24/7/15): Il est gratifiant que l'explication ci-dessus semble aider à démystifier le problème. Bien que je ne l'ai pas testé, le code de mohamede1945 [ci-dessous] ressemble à une optimisation utile à des fins pratiques. N'hésitez pas à le tester et dites-nous ce que vous en pensez. (Par souci d'exhaustivité, je laisserai l'exemple de code ci-dessus tel quel.)