web-dev-qa-db-fra.com

Vue personnalisée - self.frame n'est pas correct?

J'ai donc une classe UIView personnalisée

class MessageBox: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        createSubViews()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        createSubViews()
    }
    func createSubViews() {

        let testView = UIView(frame: self.frame)
        testView.backgroundColor = UIColor.brown
        self.addSubview(testView)
    }
}

J'ai ajouté un UIView à l'intérieur du storyboard et lui ai donné quelques contraintes:

100 du haut (superview), 0 de gauche et de droite, hauteur 180

Mais lorsque je lance l'application, la sous-vue brune que j'ai créée dans le code est trop grosse. J'ai imprimé self.frame dans mon affichage personnalisé et il s'avère que le cadre est (0,0,1000,1000). Mais pourquoi? Je pose des contraintes, ça devrait être quelque chose comme (0,0,deviceWith, 180).

 enter image description here

Qu'ai-je fait de mal?

EDIT: C'est ma configuration Storyboard:

 enter image description here

7
Quantm

Réponse courte et simple:

Tu le fais trop tôt.


Réponse détaillée:

Lorsqu'une vue est initialisée à partir d'un fichier Interface Builder (un xib ou un storyboard), son image est initialement définie sur celle du fichier Interface Builder. Vous pouvez le regarder comme un espace réservé temporaire.

Lors de l'utilisation de la disposition automatique, les contraintes sont résolues (= l'image réelle de la vue est calculée) dans la méthode layoutSubviews() de la vue.

Il existe donc deux solutions possibles à votre problème:

  1. (préférable) Si vous utilisez la disposition automatique, utilisez-la dans votre vue.

    • Ajoutez également votre testView dans Interface Builder et créez-lui un point de vente.
    • ou créez votre testView dans le code comme vous le faites, puis définissez sa propriété translatesAutoResizingMaskIntoConstraints sur false (pour trier "activer la mise en forme automatique") et ajoutez les contraintes requises dans le code.
  2. Définissez le cadre de votre testView après que le cadre de la vue MessageBox ait été défini par le moteur de présentation. Le seul endroit où vous pouvez être sûr que le système a résolu le cadre de la vue à partir des contraintes est lorsque layoutSubviews() est appelé.

    override func layoutSubviews() {
        super.layoutSubviews()
        testView.frame = self.frame
    }
    

    (Vous devez bien sûr déclarer votre testView en tant que propriété/variable globale.)

17
Mischa
override func layoutSubviews() {
    super.layoutSubviews()
    testView.frame = self.frame
}

cela fonctionne également lorsque vous ajoutez une classe personnalisée à UIView dans le storyboard et qui utilise l'autolayout. merci Mischa !

1
Murphy

Essayez d'utiliser les ancres pour votre vue: 

MessageBox.centerXAnchor.constraintEqualToAnchor(self.view.centerXAnchor).active
= true 
MessageBox.centerYAnchor.constraintEqualToAnchor(self.view.centerYAnchor).active
= true 
MessageBox.widthAnchor.constraintEqualToConstant(150).active = true 
MessageBox.heightAnchor.constraintEqualToConstant(100).active = true

Cette méthode doit être utilisée dans votre classe

1
Carlo

essayez d'ajouter une contrainte de hauteur et de largeur relative à la hauteur de la vue supérieure, avec un multiplicateur.

0
Dasem