2017-08-02 2 views
0

J'essaie de créer (par programmation) une nouvelle vue et d'utiliser l'attribut IBDesignable pour simplifier ce processus et pour afficher les vues dans le storyboard au lieu des rectangles blancs. Voici une classe avec deux sous-vues: UILabel et UIImageView Je les ajoute dynamiquement à la vue parent et définir quelques contraintes pour eux:IBDesignable View avec des contraintes dynamiques: enfants mal placés lors du rendu

import UIKit 

@IBDesignable 
class ChoiceView: UIView { 

    enum ChoiceState { 
     case empty, chosen 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     setupViewForState(.empty) 
    } 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     setupViewForState(.empty) 
    } 

    override func awakeFromNib() { 
     super.awakeFromNib() 
    } 

    override func layoutSubviews() { 
     super.layoutSubviews() 
    } 

    private func setupViewForState(_ state: ChoiceState) { 
     guard case .empty = state else { return } // single case for now 

     let placeholder = UILabel() 
     let choiceImage = UIImageView(image: UIImage(named: "plus_small")) 
     placeholder.text = "None" 
     placeholder.textAlignment = .right 
     choiceImage.contentMode = .center 

     let constraintFormats = [ 
      "H:|-0-[placeholder]-10-[choice(50)]-0-|", 
      "V:|-0-[placeholder]-0-|", 
      "V:|-0-[choice]-0-|" 
     ] 

     let views = ["placeholder": placeholder, "choice": choiceImage] 

     translatesAutoresizingMaskIntoConstraints = false 
     placeholder.translatesAutoresizingMaskIntoConstraints = false 
     choiceImage.translatesAutoresizingMaskIntoConstraints = false 
     addSubview(placeholder) 
     addSubview(choiceImage) 

     let constraints = constraintFormats.flatMap { 
      NSLayoutConstraint.constraints(
       withVisualFormat: $0, 
       options: .directionLeadingToTrailing, 
       metrics: nil, 
       views: views) 
     }   

     NSLayoutConstraint.activate(constraints) 
    } 

} 

Ce ne sont pas encore parfait, mais au moins - comme montré dans le simulateur: cell in simulator

Mais quand je recharge vues dans le générateur de storyboard, je vois ceci: cell in storyboard

Comme vous pouvez le voir, les contraintes ne sont pas appliquées dans le storyboard et l'image n'est pas affichée. Savez-vous comment résoudre ce problème? Ou, est-il même possible d'obtenir la même image dans le storyboard et le simulateur?


Solution: S'il vous plaît regarder réponse @DonMag. Cela permet de voir le résultat attendu (voir photo ci-jointe).

enter image description here

+0

Depuis IB est une conception en temps * * outil, vous ne pouvez pas attendre * Code * à traiter en elle. Donc, non, ce n'est pas possible. – dfd

+0

Je comprends, mais vous voyez, l'étiquette est affichée correctement, avec le titre défini dans le code. Par conséquent, je pense qu'il est possible de faire la même chose pour 'UIImage'. – devforfu

+0

@devforfu avez-vous vérifié ma réponse? –

Répondre

1

Ne définissez pas translatesAutoresizingMaskIntoConstraints = false pour votre vue Designable se.

let views = ["placeholder": placeholder, "choice": choiceImage] 

    // don't do this one 
    //translatesAutoresizingMaskIntoConstraints = false 
    placeholder.translatesAutoresizingMaskIntoConstraints = false 
    choiceImage.translatesAutoresizingMaskIntoConstraints = false 
    addSubview(placeholder) 
    addSubview(choiceImage) 

Aussi, pour voir votre "choix" dans l'image IB:

let theBundle = Bundle(for: type(of: self)) 
    let choiceImage = UIImageView(image: UIImage(named: "plus_small", in: theBundle, compatibleWith: self.traitCollection)) 
    // 
    //let choiceImage = UIImageView(image: UIImage(named: "plus_small")) 
    ... 
+0

Solution complètement valide. L'image et l'étiquette sont affichées et alignées correctement. – devforfu