iOS 11 de la zone de sécurité guide de présentation de rétro-compatibilité
Est l'activation de la Zone de Sécurité repères de Mise en page compatible pour iOS en dessous de 11?
12 réponses
j'ai réussi à travailler avec les nouveaux guides D'aménagement des zones de sécurité et à maintenir la compatibilité avec iOS 9 et iOS 10: (EDIT: comme l'a souligné dans les commentaires de @NickEntin, cette mise en œuvre présumer qu'il y a une barre d'état présents, ce qui ne sera pas vrai dans le paysage sur l'iPhone X. Résultant de l'espace vers le haut (20 points). Il va fonctionner parfaitement bien cependant.
E. G. si vous voulez qu'une vue soit 10 points en dessous du statut barre (et 10 points en dessous du boîtier du capteur sur iPhone X):
- dans votre XIB, allez à
File Inspector
et activez le coffre-fort sont en cochantUse Safe Area Layout Guides
. - crée une contrainte du haut de la vue au haut de la vue principale, avec
>=
(plus grande ou égale) contrainte, constante30
(30 parce que nous voulons 10 points d'espacement à la barre d'état qui est de 20 points de haut) et la prioritéHigh
(750). - Créer une contrainte du haut de la vue au haut de la zone de sécurité, avec
=
contrainte (égale), constante10
et prioritéLow
(250).
la même chose peut être faite pour une vue en bas (et pour conduire/suivre ou Gauche/Droite à la zone de sécurité):
- dans votre XIB, allez à
File Inspector
et activez le coffre-fort sont en cochantUse Safe Area Layout Guides
. - créer une contrainte à partir de la vue du bas vers le bas de la vue principale, avec la contrainte
>=
(supérieure ou égale), constante10
et prioritéHigh
(750). - crée une contrainte du fond de la vue au fond de L'aire de sécurité, avec
=
contrainte (égale), constante10
et prioritéLow
(250).
la rétrocompatibilité des zones de sécurité pour iOS 9 et iOS 10 ne fonctionne que si vous utilisez des storyboards. Si vous utilisez xibs, il n'existe pas de guide de présentation de retomber. https://forums.developer.apple.com/thread/87329
Les solutions semblent être, soit
(a) la migration de votre xibs dans les storyboards, ou
(b) ajouter des contraintes supplémentaires par programmation.
si (a) n'est pas vraiment une option, l'approche manuelle sera quelque chose comme ceci:
en supposant que vous avez une vue dans votre xib que vous voulez garder dans la zone de sécurité (c.-à-d. Sous n'importe quelle barre d'état ou barre de navigation).
-
ajouter des contraintes dans votre xib entre votre vue et la zone de sécurité pour iOS 11. Attribuer la contrainte supérieure à une priorité de 750.
-
dans votre contrôleur de vue, ajouter une propriété:
@property (nonatomic, strong) NSLayoutConstraint *topLayoutConstraint;
et puis en viewDidLayoutSubviews:
- (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; if (@available(iOS 11, *)) { // safe area constraints already set } else { if (!self.topLayoutConstraint) { self.topLayoutConstraint = [self.<yourview>.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor]; [self.topLayoutConstraint setActive:YES]; } } }
la nouvelle contrainte ne sera créée que pour iOS 9 & iOS 10, a une priorité par défaut de 1000, et supplante celle du xib.
-
répéter pour une contrainte de fond si vous devez éviter l'indicateur de maison.
Swift 4 version:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if #available(iOS 11, *) {
// safe area constraints already set
} else {
if topLayoutConstraint == nil {
topLayoutConstraint = <yourview>.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
topLayoutConstraint?.isActive = true
}
}
}
il y a certainement au moins un problème de rétrocompatibilité avec les contraintes de zones de sécurité de iOS 11 que j'ai observé dans les contrôleurs Xcode 9 GM--vue poussée avec des contraintes de zones de sécurité.
si votre barre de navigation est cachée et que vous appuyez sur une zone sûre vue TOP-constrained, la vue poussée chevauchera la barre d'état sur iOS 9 & 10.
si la barre de navigation est visible, et" sous les barres supérieures " désactivé, la vue poussée sera encore glisser vers le haut sous la barre de navigation pour atteindre le haut de l'écran. La barre de navigation est placée correctement.
sur iOS 11, la mise en page sera correcte dans les deux cas.
voici un exemple simple: http://www.filedropper.com/foobar
et voici une vidéo de lui W / nav barre cachée (iOS 10.3 à gauche, iOS 11 à droite): https://vimeo.com/234174841/1e27a96a87
voici un version où la barre de navigation est visible (activée dans la nib): https://vimeo.com/234316256/f022132d57
Je l'ai enregistré sous le numéro de Radar 34477706.
merci à @Sander pour avoir pointé le cas visible de la barre de navigation.
si vous utilisez xibs sans storyboard, il n'y a pas de guide de mise en page sur ios 10. Donc déplacez xib vers storyboard pour avoir une compatibilité arrière.
Oui, votre projet / application fonctionnera en version iOS avant iOS 11 sans aucun problème. Dans les versions iOS antérieures à 11, Il remplace / considère la disposition des zones de sécurité dans L'AutoLayout normal et suit les règles de top et de Bottom layout guide.
j'ai testé mon projet existant avec et sans "SafeAreaLayout" sur les deux plateformes (iOS 11 et backward iOS 10). Ça fonctionne très bien.
assurez-vous Simplement:
si vous avez conçu votre Interface projet/Utilisateur en AutoLayout; les contraintes de votre équipement suivent/relatives au haut et au bas guide de mise en page (pas à superview). Donc, par un simple clic (activer) sur Option SafeAreaLayout, implémente automatiquement Layout SafeArea correctement pour tous les dossiers de constructeurs D'Interface dans votre storyboard.
si vous avez conçu votre projet/interface utilisateur dans SafeAreaLayout; alors il sera automatiquement suivez le guide de mise en page en haut et en bas en arrière iOS.
voici un exemple d'instantané avec le résultat, en activant ou désactivant la disposition de la zone de sécurité, n'aura pas d'effet sur la conception existante.
mise en forme automatique
en bref, une réponse à votre question Est: "permettre des guides de mise en page des zones de sécurité compatibles avec iOS avant 11"
vous pouvez mettre en œuvre la disposition des zones de sécurité dans votre projet / Application et il fonctionnera très bien avec les versions précédentes d'iOS par conversion de la disposition des zones de sécurité en la disposition du haut et du bas.
Je l'utilisais dans Objectif-C avec un bon résultat pour iOS 10.
Dans le cas où vous utilisez SafeArea dans votre xib, vous pouvez ajouter dans votre viewDidLoad
:
if (@available(iOS 11.0, *)) {}
else {
self.edgesForExtendedLayout = UIRectEdgeNone;
}
"zone de sécurité guide de présentation de l'" est rétro-compatible. Eh bien, à moins que vous l'utilisez dans xib. Avec storyboard, ça a l'air bien.
j'ai résolu mon problème en accédant à la" top layout constraint " à partir du premier objet en haut de ma vue.
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topLayoutConstraint;
ensuite, j'ai changé la valeur constante à cette contrainte et rafraîchit la vue. Par exemple, si vous utilisez une barre de navigation (Hauteur 44) plus la barre d'état (Hauteur 20):
if (SYSTEM_VERSION_LESS_THAN(@"11.0")) {
_topLayoutConstraint.constant = 64;
[self.view layoutIfNeeded];
}
avec SYSTEM_VERSION_LESS_THAN qui est défini comme ceci:
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
j'ai des problèmes de compatibilité descendante avec WKWebView Et de la Zone de Sécurité sur iOS 9. Pour une raison ou une autre, WKWebView ne tient pas compte des paramètres d'aménagement des zones de sécurité.
en Objectif - C pour marge supérieure et inférieure sur iPhone-X
if (@available(iOS 11, *)) {
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.childView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.parentView.safeAreaLayoutGuide
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.childView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.parentView.safeAreaLayoutGuide
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0];
} else {
NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:self.childView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.parentView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:self.childView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.parentView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0];
}
voici ce que j'ai fait avec mes projets
dans mon cas, mes topConstraint
et bottomConstraint
s sont @IBOutlet
S. C'est aussi compatible pour iOS 8
.
ma configuration initiale pour les contraintes du haut et du bas est pour les iPhones normaux, c'est pourquoi je ne édite que les contraintes pour iPhone X
// iOS 11 Layout Fix. (For iPhone X)
if #available(iOS 11, *) {
self.topConstraint.constant = self.topConstraint.constant + self.view.safeAreaInsets.top
self.bottomConstraint.constant = self.bottomConstraint.constant + self.view.safeAreaInsets.bottom
}
.
NOTE: self.view
est votre superView c'est pourquoi je l'utilise pour safeAreaInsets
lorsque vous avez un ViewController générique que tous vos ViewControllers étendent, une autre solution serait de mettre les éléments qui doivent être ajustés dans une Collecti on Iboutletet et de les ajuster programmatiquement dans ce ViewController Générique. Voici mon code:
@IBOutlet var adjustTopSpaceViews: [UIView]?
override func viewDidLoad() {
super.viewDidLoad()
adjustViews()
....
}
func adjustViews() {
guard let views = adjustTopSpaceViews,
ProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11 else {
return
}
let statusBarHeight = UIApplication.shared.statusBarFrame.height
for subview in views {
subview.superview?.constraints.filter({ (constraint) -> Bool in
return constraint.firstAttribute == .top
&& constraint.secondAttribute == .top
&& (constraint.firstItem as? UIView == subview || constraint.secondItem as? UIView == subview)
}).forEach({ (constraint) in
constraint.constant += (constraint.firstItem as? UIView == subview) ? statusBarHeight : -statusBarHeight
})
}
}
j'ai trouvé un moyen plus pratique où vous avez seulement besoin de sous-classe le NSLayoutConstraint
qui est épinglé à votre safeArea
.
c'est un peu hacky puisque vous devez obtenir le ViewController à partir d'un uivi, mais à mon avis, c'est une alternative facile et bonne jusqu'à ce Qu'Apple corrige enfin la compatibilité en arrière pour la zone de sécurité dans Xibs.
sous-classe:
class SafeAreaBackwardsCompatabilityConstraint: NSLayoutConstraint {
private weak var newConstraint: NSLayoutConstraint?
override var secondItem: AnyObject? {
get {
if #available(iOS 11.0, *) {}
else {
if let vc = (super.secondItem as? UIView)?.parentViewController, newConstraint == nil {
newConstraint = (self.firstItem as? UIView)?.topAnchor.constraint(equalTo: vc.topLayoutGuide.bottomAnchor)
newConstraint?.isActive = true
newConstraint?.constant = self.constant
}
}
return super.secondItem
}
}
override var priority: UILayoutPriority {
get {
if #available(iOS 11.0, *) { return super.priority }
else { return 750 }
}
set { super.priority = newValue }
}
}
private extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.next
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}
Xib: