web-dev-qa-db-fra.com

Dimensionnement d'une vue conteneur avec un contrôleur de taille dynamique dans une vue à défilement

J'essaie de créer une vue de conteneur, avec un contrôleur doté d'une hauteur dynamique, dans un UIScrollView et de le redimensionner automatiquement à l'aide de la disposition automatique.

Storyboard illustrating the setup

Le contrôleur de vue A est la vue de défilement, qui comprend la vue du conteneur, ainsi que plus de contenu ci-dessous.

View Controller B est le contrôleur de vue pour lequel je souhaite avoir une taille dynamique et pour que tout le contenu soit affiché en hauteur dans la vue de défilement de View Controller A.

Je ne parviens pas à obtenir la taille dynamique de B pour définir automatiquement la taille de la vue conteneur dans A. Cependant, si je définis une contrainte de hauteur sur la vue conteneur dans A Container View in A to for example 250

Ce serait la sortie attendue si View Controller B aurait également une hauteur de 250. Cela fonctionne aussi très bien pour la hauteur 1000, donc, autant que je sache, toutes les contraintes de mise en page automatique sont correctement configurées. Malheureusement, comme la hauteur doit être dynamique, j'aimerais éviter de définir une contrainte de hauteur. 

Je ne sais pas s'il existe des paramètres pour le contrôleur de vue B, mais je peux le configurer pour qu'il mette automatiquement à jour sa taille en fonction de son contenu ou s'il y a d'autres astuces que j'ai ratées. Toute aide serait très appréciée!

Existe-t-il un moyen de dimensionner la vue conteneur dans A en fonction de la taille de View Controller B sans définir de contrainte de hauteur?

51

Yup, il y a. J'ai réussi à obtenir ce genre de comportement dans l'un de mes propres projets.

Tout ce que vous avez à faire, c'est d'indiquer au système qu'il ne doit pas ajouter de contraintes qui imitent le jeu d'images fixes défini pour votre vue racine dans Interface Builder. Le meilleur endroit pour le faire est dans votre contrôleur de vue du conteneur lorsque votre séquence d'intégration est déclenchée:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // You might want to check if this is your embed segue here
    // in case there are other segues triggered from this view controller. 
    segue.destinationViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
}

Important:

Vous devez vous assurer que la vue que vous chargez dans le conteneur est contrainte de haut en bas et que vous devez définir la priorité de l'une des contraintes verticales sur une valeur inférieure à 1000. (Il est recommandé de toujours utiliser la contrainte inférieure. pour cela.) Cela est nécessaire car sinon, Interface Builder se plaindra - avec une bonne raison: 

Au moment de la conception, votre vue racine a une taille fixe (hauteur). Désormais, si toutes vos sous-vues ont une hauteur fixe et sont liées à des contraintes fixes ayant la même priorité, il est impossible de satisfaire à toutes ces exigences, à moins que la hauteur de votre vue racine fixe corresponde par hasard à la hauteur totale de vos sous-vues et aux contraintes verticales. Si vous réduisez la priorité d'une des contraintes à 999, Interface Builder sait quelle contrainte doit être rompue. Toutefois, au moment de l'exécution (lorsque la propriété translatesAutoresizingMaskIntoConstraints est définie comme indiqué ci-dessus), il n'y a plus de cadre fixe pour votre vue racine et le système utilisera votre contrainte de priorité 999 à la place.

 Interface Builder Screenshot

80
Mischa

De la réponse de @Mischa, j'ai pu rendre dynamique la hauteur d'un conteneurView en fonction de son contenu:

Dans le viewController de containerView, écrivez:

  override func loadView() {
    super.loadView()
    view.translatesAutoresizingMaskIntoConstraints = false
  }

Et en veillant à ce que les contraintes verticales dans IB soient toutes définies. Pour ce faire, vous n'avez pas besoin de définir view.translatesAutoresizingMaskIntoConstraints = false en dehors du contrôleur de vue.

Dans mon cas, j'essayais de redimensionner le conteneur en un tableau dans le viewController. Parce que la tableView a une hauteur flexible en fonction de son aperçu (donc tout va bien pour IB), j'ai complété les contraintes verticales dans le code en procédant comme suit:

  @IBOutlet private var tableView: UITableView! {
    didSet {
      tableView.addConstraint(tableViewHeight)
    }
  }
  private lazy var tableViewHeight: NSLayoutConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 0)

Observez ensuite la hauteur contentSize de la vue table et ajustez la constante de la contrainte tableViewHeight par programme si nécessaire.

20
acecilia