2017-10-14 27 views
1

J'ai créé un UIButton au milieu d'un TabBarController mais il n'est pas correctement affiché sur l'iPhone X en raison de ses zones de sécurité au bas du téléphone.Création d'un UIButton par programmation sur l'iPhone X mais zone sûre

override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 
    //Frame mic button 
    micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124) 
    micButton.layer.cornerRadius = 62   
} 

enter image description here

Quelle est la bonne façon de tirer cette UIButton sans toucher les zones de sécurité.

+0

de UITabViewController Le code affiché n'empanner pas du tout avec tout ce qui concerne la mise en page automatique. (1) Pourquoi définissez-vous des valeurs de cadre? C'est probablement la chose la plus importante. (2) Les zones de sécurité impliquent généralement - peut-être même absolument - des contraintes. Où sont-elles? Par ceci je veux demander ... (3) Une "zone sûre" pour l'iPhone X - et par définition, iOS 11 - signifie 'safeAreaLayoutGuide'. Alors pourquoi affichez-vous du code qui n'utilise pas ceci ou toute autre * contrainte de mise en page automatique? – dfd

+0

@dfd c'est vrai mais je n'ai jamais fait de mise en page par programmation si vous connaissez un bon guide de contraintes programmatiques ou un tutoriel qui serait génial. Plus je pensais qu'il y aurait différentes propriétés de vue que je ne sais pas qui calcule le cadre de vue à partir des zones de sécurité. Ou est-ce que tout dépend des contraintes? –

+0

Permettez-moi de poster une réponse programmatique. Il peut être incomplet ou même sans valeur. Mais j'espère que ce n'est ni l'un ni l'autre et cela aidera. (Et s'il manque quelque chose, poster un commentaire et je vais éditer.) – dfd

Répondre

1

Les zones sécurisées, en particulier safeAreaLayoutGuide, se rapportent à des contraintes.

Il existe plusieurs façons de coder les contraintes de mise en page automatique (Visual Format Layout ou VFL, explicite - et verbeuse - NSLayoutConstraints) mais ma préférence est d'utiliser des «ancres de mise en page».

L'idée de base pour toute disposition est position et taille. Donnez quelque chose d'une largeur/hauteur, et la valeur de l'axe x/y et vous l'avez. Assez comme des cadres.

Ainsi, la manière "d'ancrage" de base de pose cette:

micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124) 

serait:

let micButton = UIButton() 
micButton.translatesAutoresizingMaskIntoConstraints = false 

micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -94).isActive = true 
micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true 
micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true 
micButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: -62).isActive = true 

Quelques notes:

  • Oui, vous ne dictons pas Cadre. En fait, vous initialisez simplement les choses quand c'est possible.
  • Étant donné que vous n'utilisez pas IB, vous devez définir l'indicateur de masque de redimensionnement automatique sur false. C'est quelque chose que même les développeurs les plus expérimentés oublient parfois. (Cela signifie généralement que vous avez des résultats «inattendus» allant de ne pas voir quelque chose à le voir mal placé.)
  • J'ai défini l'axe du bas ou Y, la largeur et la hauteur, et enfin l'axe X.

Bien que ce soit plus de code que d'utiliser un cadre, ce que vous obtenez est la cohérence entre les tailles d'écran.

Mais vous en voulez plus - vous devez coder pour les zones sécurisées de l'iPhone X. Vous avez deux outils Apple vous a donné: layoutMarginsGuide et safeAreaLayoutGuide. Le premier a été introduit dans iOS 9 (avec les plus simples layoutGuide et les ancres de mise en page) tandis que le dernier a été introduit dans iOS 11.

[Ma supposition, probablement une sécurité, est que tous les appareils iPhone X fonctionneront sous iOS 11 ou plus tard. Depuis une « zone de sécurité » est vraiment nécessaire que pour cet appareil, ce qui suit est ce que vous avez besoin.]

marges travail avec tous dispositifs de premier plan/arrière (ou horizontales) bords. Ils fonctionnent également pour les bords supérieurs/inférieurs (ou verticaux). Mais pour l'iPhone X, vous devez vous préoccuper d'un haut/bas différent, donc de la "zone de sécurité".

let layoutGuideTop = UILayoutGuide() 
let layoutGuideBottom = UILayoutGuide() 
view.addLayoutGuide(layoutGuideTop) 
view.addLayoutGuide(layoutGuideBottom) 
let margins = view.layoutMarginsGuide 
view.addLayoutGuide(margins) 
if #available(iOS 11, *) { 
    let guide = view.safeAreaLayoutGuide 
    layoutGuideTop.topAnchor.constraintEqualToSystemSpacingBelow(guide.topAnchor, multiplier: 1.0).isActive = true 
    layoutGuideBottom.bottomAnchor.constraintEqualToSystemSpacingBelow(guide.bottomAnchor, multiplier: 1.0).isActive = true 
} else { 
    layoutGuideTop.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true 
    layoutGuideBottom.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true 
} 

L'extrait de code ci-dessus donnera les variables de marge haut/bas correct (layoutGuideTop et layoutGuideBottom) basé sur la version iOS.De là, vous pouvez régler votre point d'ancrage à fond:

micButton.bottomAnchor.constraint(equalTo: laytouGuideBottom, constant: -94).isActive = true 

qui devrait fixer micButton de 94 points au-dessus du fond zone de sécurité.

est ici quelques liens qui devraient vous aider avec des ancres de mise en page et guides:

Layout Anchors

Layout Guides

Safe Area Layout Guides

EDIT:

Une dernière note sur les contraintes . Comme vous ne comptez pas sur des valeurs de trames, tout ce code est mieux placé dans viewDidLoad, car le moteur de disposition va tout déterminer de manière appropriée (et viewDidLayoutSubviews peut être appelé plusieurs fois).

0

Grâce aux conseils de @dfd, c'était comme ça que je travaillais. Je viens de vérifier si le téléphone en utilisant l'application a la même taille d'écran que iPhoneX et j'ai juste changé dans les contraintes.

override func viewDidLoad() { 
    super.viewDidLoad() 

    //Frame mic button 
    micButton.frame = CGRect.init(x: self.tabBar.center.x - 62, y: self.view.bounds.height - 94, width: 124, height: 124) 
    micButton.layer.cornerRadius = 62 
    micButton.translatesAutoresizingMaskIntoConstraints = false 

    micButton.setBackgroundImage(#imageLiteral(resourceName: "micIcon"), for: .normal) 
    //Add to tabbar view 
    self.view.insertSubview(micButton, aboveSubview: self.tabBar) 


    if UIDevice().userInterfaceIdiom == .phone { 
     if UIScreen.main.nativeBounds.height == 2436 { 
      //iPhoneX Device 
      micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true 
      micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true 
      micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true 
      micButton.centerXAnchor.constraint(equalTo: self.tabBar.centerXAnchor, constant: 0).isActive = true 
     } else { 
      //Not an iPhoneX Device 
      micButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 25).isActive = true 
      micButton.widthAnchor.constraint(equalToConstant: 124).isActive = true 
      micButton.heightAnchor.constraint(equalToConstant: 124).isActive = true 
      micButton.centerXAnchor.constraint(equalTo: self.tabBar.centerXAnchor, constant: 0).isActive = true 
     } 

    } 

    // Do any additional setup after loading the view. 
} 
1

Essayez ceci:

Ajouter dans la classe

micButton.translatesAutoresizingMaskIntoConstraints = false 
view.addSubview(micButton) 
    if #available(iOS 11, *) { 
     let guide = view.safeAreaLayoutGuide 
     micButton.centerXAnchor.constraint(equalTo: guide.centerXAnchor).isActive = true 
     micButton.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true 
     micButton.heightAnchor.constraint(equalToConstant: 64).isActive = true 
     micButton.widthAnchor.constraint(equalToConstant: 64).isActive = true 

    } else { 
     NSLayoutConstraint(item: micButton, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0).isActive = true 
     NSLayoutConstraint(item: micButton, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0).isActive = true 
     micButton.heightAnchor.constraint(equalToConstant: 64).isActive = true 
     micButton.widthAnchor.constraint(equalToConstant: 64).isActive = true 
      }