Quelqu'un peut-il me dire s'il vous plaît quelle est la "bonne" ou la "meilleure" approche pour travailler avec les orientations d'interface portrait et paysage dans iOS 8? Il semble que toutes les fonctions que je souhaite utiliser à cet effet soient obsolètes dans iOS 8, et mes recherches n’ont abouti à aucune alternative claire et élégante. Suis-je vraiment censé regarder la largeur et la hauteur pour déterminer moi-même si nous sommes en mode portrait ou paysage?
Par exemple, dans mon contrôleur de vue, comment dois-je implémenter le pseudocode suivant?
if we are rotating from portrait to landscape then
do portrait things
else if we are rotating from landscape to portrait then
do landscape things
Apple recommande d’utiliser les classes de taille comme mesure approximative de la quantité d’espace disponible sur l’écran, afin que votre interface utilisateur puisse changer de manière significative sa disposition et son apparence. Considérez qu'un iPad en portrait a les mêmes classes de taille que dans le paysage (largeur normale, hauteur normale). Cela signifie que votre interface utilisateur doit être plus ou moins similaire entre les deux orientations.
Cependant, le passage de portrait en paysage dans un iPad est suffisamment important pour que vous deviez peut-être effectuer quelques ajustements moins importants de l'interface utilisateur, même si les classes de taille n'ont pas changé. Puisque les méthodes liées à l'orientation de l'interface sur UIViewController
sont obsolètes, Apple recommande désormais d'implémenter la nouvelle méthode suivante dans UIViewController
en remplacement:
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
// Code here will execute before the rotation begins.
// Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Place code here to perform animations during the rotation.
// You can pass nil or leave this block empty if not necessary.
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
// Code here will execute after the rotation has finished.
// Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]
}];
}
Génial! Vous recevez maintenant des rappels juste avant le début et après la fin de la rotation. Mais qu'en est-il de savoir réellement si la rotation est au portrait ou au paysage?
Apple recommande de considérer la rotation comme un simple changement de taille de la vue parente. En d'autres termes, lors d'une rotation iPad de portrait en paysage, vous pouvez la considérer comme une vue de niveau racine modifiant simplement son bounds.size
de {768, 1024}
à {1024, 768}
. Sachant cela, vous devez utiliser la méthode size
passée dans la méthode viewWillTransitionToSize:withTransitionCoordinator:
ci-dessus pour déterminer si vous effectuez une rotation en mode portrait ou paysage.
Si vous souhaitez un moyen encore plus transparent de migrer le code hérité vers le nouveau mode de fonctionnement iOS 8, envisagez d'utiliser cette catégorie simple sur UIView, qui peut être utilisé pour déterminer si une vue est "portrait". ou "paysage" en fonction de sa taille.
Récapituler:
viewWillTransitionToSize:withTransitionCoordinator:
dans UIViewController.statusBarOrientation
, qui est essentiellement une propriété au niveau du périphérique, pour déterminer si vous souhaitez mettre en forme une vue pour "portrait" ou "paysage". L'orientation de la barre d'état ne doit être utilisée que par le code traitant d'éléments tels que UIWindow
, qui résident en réalité au niveau racine de l'application.Sur la base de la réponse très bien détaillée (et acceptée) de smileyborg, voici une adaptation utilisant Swift 3:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: nil, completion: {
_ in
self.collectionView.collectionViewLayout.invalidateLayout()
})
}
Et dans la UICollectionViewDelegateFlowLayout
mise en œuvre,
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// retrieve the updated bounds
let itemWidth = collectionView.bounds.width
let itemHeight = collectionView.bounds.height
// do whatever you need to do to adapt to the new size
}
J'utilise simplement Notification Center:
Ajouter une variable d'orientation (expliquera à la fin)
//Above viewdidload
var orientations:UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation
Ajouter une notification lorsque la vue apparaît
override func viewDidAppear(animated: Bool) {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: UIDeviceOrientationDidChangeNotification, object: nil)
}
Supprimer la notification lorsque la vue disparaît
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIDeviceOrientationDidChangeNotification, object: nil)
}
Obtient l'orientation actuelle lorsque la notification est déclenchée
func orientationChanged (notification: NSNotification) {
adjustViewsForOrientation(UIApplication.sharedApplication().statusBarOrientation)
}
Vérifie l'orientation (portrait/paysage) et gère les événements
func adjustViewsForOrientation(orientation: UIInterfaceOrientation) {
if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown)
{
if(orientation != orientations) {
println("Portrait")
//Do Rotation stuff here
orientations = orientation
}
}
else if (orientation == UIInterfaceOrientation.LandscapeLeft || orientation == UIInterfaceOrientation.LandscapeRight)
{
if(orientation != orientations) {
println("Landscape")
//Do Rotation stuff here
orientations = orientation
}
}
}
La raison pour laquelle j'ai ajouté une variable d'orientation est que, lors des tests sur un périphérique physique, la notification d'orientation est appelée à chaque déplacement mineur du périphérique, et pas uniquement lors de sa rotation. L'ajout des instructions var et if n'appelle le code que s'il a basculé dans l'orientation opposée.
Du point de vue de l'interface utilisateur, l'utilisation des classes de taille est l'approche recommandée par Apple pour la gestion des interfaces dans différentes orientations, tailles et échelles.
Voir la section: Traits Décrivez la classe de taille et l'échelle d'une interface ici: https://developer.Apple.com/library/ios/releasenotes/General/ WhatsNewIniOS/Articles/iOS8.html
"iOS 8 ajoute de nouvelles fonctionnalités qui rendent la gestion de la taille et de l'orientation de l'écran beaucoup plus polyvalente."
Celui-ci est également un bon article: https://carpeaqua.com/thinking-in-terms-of-ios-8-size-classes/
EDIT Lien mis à jour: https://carpeaqua.com/2014/06/14/thinking-in-terms-of-ios-8-size-classes/ (Crédit: Koen)