111 votes

Comment puis-je utiliser la mise en page de la zone de sécurité de manière programmatique ?

Comme je n'utilise pas de storyboards pour créer mes vues, je me demandais s'il existait une option "Utiliser les guides de zones sûres" par programmation ou quelque chose du genre.

J'ai essayé d'ancrer mes opinions à

view.safeAreaLayoutGuide

mais ils continuent de chevaucher l'encoche supérieure dans le simulateur de l'iPhone X.

1 votes

Aucune propriété bool documentée à ce sujet selon : developer.apple.com/documentation/uikit/uiview/

0 votes

Et si view.safeAreaInsets ? Avez-vous essayé ?

0 votes

@KarthikeyanBose Oui, je l'ai fait, mais sans succès malheureusement.

180voto

Krunal Points 33551

Voici un exemple de code (Ref de : Guide d'aménagement des zones de sécurité ) :
Si vous créez vos contraintes dans le code, utilisez la propriété safeAreaLayoutGuide de UIView pour obtenir les ancres de disposition pertinentes. Recréons l'exemple d'Interface Builder ci-dessus dans le code pour voir à quoi cela ressemble :

En supposant que nous avons la vue verte comme une propriété dans notre contrôleur de vue :

private let greenView = UIView()

Nous pourrions avoir une fonction pour configurer les vues et les contraintes appelée par viewDidLoad :

private func setupView() {
  greenView.translatesAutoresizingMaskIntoConstraints = false
  greenView.backgroundColor = .green
  view.addSubview(greenView)
}

Créez les contraintes de marge avant et arrière comme toujours en utilisant le guide layoutMargins de la vue Root :

 let margins = view.layoutMarginsGuide
 NSLayoutConstraint.activate([
    greenView.leadingAnchor.constraint(equalTo: margins.leadingAnchor),
    greenView.trailingAnchor.constraint(equalTo: margins.trailingAnchor)
 ])

Désormais, à moins que vous ne visiez iOS 11 ou une version ultérieure, vous devrez entourer les contraintes du guide de mise en page de la zone de sécurité de #disponible et revenir aux guides de mise en page supérieur et inférieur pour les versions antérieures d'iOS :

if #available(iOS 11, *) {
  let guide = view.safeAreaLayoutGuide
  NSLayoutConstraint.activate([
   greenView.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0),
   guide.bottomAnchor.constraintEqualToSystemSpacingBelow(greenView.bottomAnchor, multiplier: 1.0)
   ])
} else {
   let standardSpacing: CGFloat = 8.0
   NSLayoutConstraint.activate([
   greenView.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: standardSpacing),
   bottomLayoutGuide.topAnchor.constraint(equalTo: greenView.bottomAnchor, constant: standardSpacing)
   ])
}

Résultat :

enter image description here

enter image description here

Voici la documentation officielle des développeurs d'Apple pour Guide d'aménagement des zones de sécurité

Safe Area doit s'occuper de la conception de l'interface utilisateur pour l'iPhone-X. Voici les lignes directrices de base pour Comment concevoir une interface utilisateur pour l'iPhone-X en utilisant le Safe Area Layout

2 votes

Serait-il possible de le faire en Objective-C également ? On dirait que c'est exactement ce dont j'ai besoin

6 votes

@TomHammond Voici en Objective-C pour vous stackoverflow.com/a/47076040/5638630

0 votes

Devrions-nous vraiment vérifier via l'OS et non via le dispositif ? J'entends par là ce code #available(iOS 11, *)

89voto

Alper Points 489

J'utilise en fait une extension pour ça et je contrôle si c'est iOS 11 ou pas.

extension UIView {

  var safeTopAnchor: NSLayoutYAxisAnchor {
    if #available(iOS 11.0, *) {
      return safeAreaLayoutGuide.topAnchor
    }
    return topAnchor
  }

  var safeLeftAnchor: NSLayoutXAxisAnchor {
    if #available(iOS 11.0, *){
      return safeAreaLayoutGuide.leftAnchor
    }
    return leftAnchor
  }

  var safeRightAnchor: NSLayoutXAxisAnchor {
    if #available(iOS 11.0, *){
      return safeAreaLayoutGuide.rightAnchor
    }
    return rightAnchor
  }

  var safeBottomAnchor: NSLayoutYAxisAnchor {
    if #available(iOS 11.0, *) {
      return safeAreaLayoutGuide.bottomAnchor
    }
    return bottomAnchor
  }
}

0 votes

C'est une façon si simple de faire les choses et ça fait l'affaire. Merci pour l'idée.

1 votes

C'est une façon si simple et si agréable de le faire ! Notez l'utilisation de self.safeAreaLayoutGuide au lieu de self.layoutMarginsGuide . Le coffre-fort utilisé dans cette réponse a fonctionné correctement pour moi afin de rester dans la zone de sécurité ! Une chose que je suggérerais de changer serait d'utiliser leadingAnchor y trailingAnchor au lieu de leftAnchor y rightAnchor . Bravo !

23voto

Jack Points 4771

SafeAreaLayoutGuide es UIView propriété,

Le haut du safeAreaLayoutGuide indique le bord supérieur non masqué de la vue (par ex. de l'affichage (par exemple, pas derrière la barre d'état ou la barre de navigation, si elle est présente). Il en va de même pour les autres bords.

Utilisez safeAreaLayoutGuide pour éviter que nos objets ne s'écrêtent/se chevauchent à partir de coins arrondis, de barres de navigation, de barres d'onglets, de barres d'outils et d'autres vues ancêtres.

Nous pouvons créer safeAreaLayoutGuide les contraintes de l'objet et de l'ensemble de l'objet respectivement.

Les contraintes pour Portrait + Paysage sont -

Portrait image

Landscape image

        self.edgesForExtendedLayout = []//Optional our as per your view ladder

        let newView = UIView()
        newView.backgroundColor = .red
        self.view.addSubview(newView)
        newView.translatesAutoresizingMaskIntoConstraints = false
        if #available(iOS 11.0, *) {
            let guide = self.view.safeAreaLayoutGuide
            newView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
            newView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
            newView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
            newView.heightAnchor.constraint(equalToConstant: 100).isActive = true

        }
        else {
            NSLayoutConstraint(item: newView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0).isActive = true
            NSLayoutConstraint(item: newView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0).isActive = true
            NSLayoutConstraint(item: newView, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1.0, constant: 0).isActive = true

            newView.heightAnchor.constraint(equalToConstant: 100).isActive = true
        }

UILayoutGuide

safeAreaLayoutGuide

2 votes

Ne faites jamais de contraintes de configuration dans le viewDidAppear à moins que vous ne sachiez absolument ce que vous faites. viewDidAppear est appelé plusieurs fois et donc, vos contraintes seront dupliquées à chaque fois qu'il est appelé.

0 votes

Oui, réponse éditée, vous pouvez l'utiliser comme votre cas d'utilisation.

14voto

Pheel Points 859

Pour ceux d'entre vous qui utilisent SnapKit tout comme moi, la solution consiste à ancrer vos contraintes à view.safeAreaLayoutGuide comme ça :

yourView.snp.makeConstraints { (make) in
    if #available(iOS 11.0, *) {
        //Bottom guide
        make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottomMargin)
        //Top guide
        make.top.equalTo(view.safeAreaLayoutGuide.snp.topMargin)
        //Leading guide
        make.leading.equalTo(view.safeAreaLayoutGuide.snp.leadingMargin)
        //Trailing guide
        make.trailing.equalTo(view.safeAreaLayoutGuide.snp.trailingMargin)

     } else {
        make.edges.equalToSuperview()
     }
}

1 votes

Excellente réponse. Pour le rendre un peu plus compact, vous pourriez dire : if #available(iOS 11.0, *) { make.edges.equalTo(view.safeAreaLayoutGuide.snp.margins) }

9voto

Tony TRAN Points 1444

J'utilise cette méthode au lieu d'ajouter des contraintes de marge avant et arrière dans le guide des marges (layoutMarginsGuide) :

UILayoutGuide *safe = self.view.safeAreaLayoutGuide;
yourView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
                                           [safe.trailingAnchor constraintEqualToAnchor:yourView.trailingAnchor],
                                           [yourView.leadingAnchor constraintEqualToAnchor:safe.leadingAnchor],
                                           [yourView.topAnchor constraintEqualToAnchor:safe.topAnchor],
                                           [safe.bottomAnchor constraintEqualToAnchor:yourView.bottomAnchor]
                                          ]];

Veuillez également vérifier l'option pour la version inférieure de ios 11 dans la réponse de Krunal.

0 votes

Assurez-vous que vous avez déjà ajouté votreView à la superView. C'est self.view dans mon code comme un simple exemple.

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