Utiliser la disposition de la zone de sécurité par programme

Comme je n'utilise pas de storyboards pour créer mes vues, je me demandais s'il y avait l'option "Utiliser des Guides de zone de sécurité" par programmation ou quelque chose comme ça.

J'ai essayé d'ancrer mes vues à

view.safeAreaLayoutGuide

Mais ils continuent à chevaucher le haut de gamme dans le simulateur iPhone X.

44
demandé sur Krunal 2017-09-20 11:30:20

9 réponses

Voici un exemple de code (Réf à partir de: Zone de Sécurité Guide de Présentation de l'):
Si vous créez vos contraintes dans le code, utilisez la propriété safeAreaLayoutGuide de UIView pour obtenir les ancres de mise en page pertinentes. Recréons l'exemple de générateur d'Interface ci-dessus dans le code pour voir à quoi il ressemble:

En supposant que nous avons la vue verte en tant que 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ées à partir de viewDidLoad:

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

Créer le contraintes de marge de début et de fin comme toujours en utilisant le layoutMarginsGuide de la vue racine:

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

Maintenant, à moins que vous ne cibliez iOS 11 uniquement, vous devrez envelopper les contraintes du guide de mise en page de zone sécurisée avec #available et revenir aux guides de mise en page haut et bas 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:

entrez la description de l'image ici

entrez la description de l'image ici


Voici la Documentation officielle du développeur Apple pour Safe Area Layout Guide de


la zone de sécurité est nécessaire pour gérer la conception de l'interface utilisateur pour iPhone-X. Voici les directives de base pour Comment concevoir une interface utilisateur pour iPhone-X en utilisant la disposition de la zone de sécurité

73
répondu Krunal 2017-10-17 11:38:19

Je suis en train d'utiliser une extension pour cela et de contrôler si c'est ios 11 ou non.

extension UIView {

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

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

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

  var safeBottomAnchor: NSLayoutYAxisAnchor {
    if #available(iOS 11.0, *) {
      return self.safeAreaLayoutGuide.bottomAnchor
    } else {
      return self.bottomAnchor
    }
  }
}
39
répondu Alper 2017-11-28 14:38:20

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

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()
     }
}
6
répondu Phillip 2017-11-08 11:03:27

J'utilise ceci au lieu d'ajouter des contraintes de marge de début et de fin au 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 cocher l'option pour la version inférieure d'ios 11 de la réponse de Krunal.

5
répondu Tony Tran 2017-10-11 06:32:21

SafeAreaLayoutGuide est UIView propriété,

Le haut du safeAreaLayoutGuide indique le bord supérieur non obstrué de la vue (par exemple, pas derrière la barre d'état ou la barre de navigation, le cas échéant). De même pour les autres bords.

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

Nous pouvons créer safeAreaLayoutGuide objet et définir des contraintes d'objet respectivement.

Contraintes pour Portrait + paysage est -

Portrait d'image

Image de paysage

        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

4
répondu Jack 2017-11-10 02:34:20

Utiliser UIWindow ou UIView's safeAreaInsets .bottom .top .left .right

// #available(iOS 11.0, *)
// height - UIApplication.shared.keyWindow!.safeAreaInsets.bottom

// On iPhoneX
// UIApplication.shared.keyWindow!.safeAreaInsets.top =  44
// UIApplication.shared.keyWindow!.safeAreaInsets.bottom = 34

// Other devices
// UIApplication.shared.keyWindow!.safeAreaInsets.top =  0
// UIApplication.shared.keyWindow!.safeAreaInsets.bottom = 0

// example
let window = UIApplication.shared.keyWindow!
let viewWidth = window.frame.size.width
let viewHeight = window.frame.size.height - window.safeAreaInsets.bottom
let viewFrame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight)
let aView = UIView(frame: viewFrame)
aView.backgroundColor = .red
view.addSubview(aView)
aView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
3
répondu Warif Akhand Rishi 2018-05-09 04:45:13

Extension de la zone de sécurité pour Objective-C

@implementation UIView (SafeArea)

- (NSLayoutAnchor *)safeTopAnchor{

    if (@available(iOS 11.0, *)){
        return self.safeAreaLayoutGuide.topAnchor;
    } else {
        return self.topAnchor;
    }

}


- (NSLayoutAnchor *)safeBottomAnchor{

    if (@available(iOS 11.0, *)) {
        return self.safeAreaLayoutGuide.bottomAnchor;
    } else {
        return self.bottomAnchor;
    }

}

@end
2
répondu black_pearl 2018-09-07 18:43:14

Utilisez des contraintes avec un format visuel et vous obtenez le respect de la zone de sécurité gratuitement.

class ViewController: UIViewController {

    var greenView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        greenView.backgroundColor = .green
        view.addSubview(greenView)
    }
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()

        greenView.translatesAutoresizingMaskIntoConstraints = false
        let views : [String:Any] = ["greenView":greenView]
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[greenView]-|", options: [], metrics: nil, views: views))
        view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[greenView]-|", options: [], metrics: nil, views: views))
    }
}

résultat

0
répondu Chris Woolfe 2018-01-24 20:53:32

Vous pouvez utiliser la vue .safeAreaInsets, comme expliqué ici https://www.raywenderlich.com/174078/auto-layout-visual-format-language-tutorial-2

Exemple de Code (tiré de raywenderlich.com):

override func viewSafeAreaInsetsDidChange() {
  super.viewSafeAreaInsetsDidChange()

  if !allConstraints.isEmpty {
    NSLayoutConstraint.deactivate(allConstraints)
    allConstraints.removeAll()
  }

  let newInsets = view.safeAreaInsets
  let leftMargin = newInsets.left > 0 ? newInsets.left : Metrics.padding
  let rightMargin = newInsets.right > 0 ? newInsets.right : Metrics.padding
  let topMargin = newInsets.top > 0 ? newInsets.top : Metrics.padding
  let bottomMargin = newInsets.bottom > 0 ? newInsets.bottom : Metrics.padding

  let metrics = [
    "horizontalPadding": Metrics.padding,
    "iconImageViewWidth": Metrics.iconImageViewWidth,
    "topMargin": topMargin,
    "bottomMargin": bottomMargin,
    "leftMargin": leftMargin,
    "rightMargin": rightMargin]
}


let views: [String: Any] = [
  "iconImageView": iconImageView,
  "appNameLabel": appNameLabel,
  "skipButton": skipButton,
  "appImageView": appImageView,
  "welcomeLabel": welcomeLabel,
  "summaryLabel": summaryLabel,
  "pageControl": pageControl]

let iconVerticalConstraints = NSLayoutConstraint.constraints(
  withVisualFormat: "V:|-topMargin-[iconImageView(30)]",
  metrics: metrics,
  views: views)
allConstraints += iconVerticalConstraints

let topRowHorizontalFormat = """
  H:|-leftMargin-[iconImageView(iconImageViewWidth)]-[appNameLabel]-[skipButton]-rightMargin-|
  """
...
0
répondu Serg 2018-07-31 13:28:37