2017-10-19 6 views
1

L'affaire va comme ceci: j'ai une embed forme dans un UIScrollView, sous la forme il y a une partie où l'utilisateur peut ajouter des numéros N de textField, donc si j'ai d'abord eu ceci:Comment ajouter UITextField par programmation à UIScrollView sans casser les contraintes?

UITextField - textField1 
UIButton - Add 

Lorsque Add est pressé que je veux avoir ceci:

UITextField - textField1 
UITextField - textField2 
UIButton - Add 

et bien que le champ de texte est ajouté, les contraintes ne peuvent pas être satisfaits et donc la casse UI

behavior

Le journal que:

[LayoutConstraints] Unable to simultaneously satisfy constraints. 
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
     (1) look at each constraint and try to figure out which you don't expect; 
     (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<_UILayoutSupportConstraint:0x1c4c800a0 _UILayoutGuide:0x106ccf4e0.height == 64 (active)>", 
    "<_UILayoutSupportConstraint:0x1c4c80050 V:|-(0)-[_UILayoutGuide:0x106ccf4e0] (active, names: '|':UIView:0x106ccdc10)>", 
    "<_UILayoutSupportConstraint:0x1c4c80ff0 _UILayoutGuide:0x106ccf6d0.height == 0 (active)>", 
    "<_UILayoutSupportConstraint:0x1c4c801e0 _UILayoutGuide:0x106ccf6d0.bottom == UIView:0x106ccdc10.bottom (active)>", 
    "<NSLayoutConstraint:0x1c4c80550 UIImageView:0x106cce6c0.height == 5 (active)>", 
    "<NSLayoutConstraint:0x1c4c80640 UILabel:0x106ccf070'Completa tu Perfil'.height == 24 (active)>", 
    "<NSLayoutConstraint:0x1c0c886b0 form-view.height == 579 (active, names: form-view:0x10ed307c0)>", 
    "<NSLayoutConstraint:0x1c0c8a1e0 V:|-(0)-[form-view] (active, names: form-view:0x10ed307c0, '|':UIScrollView:0x107a37000)>", 
    "<NSLayoutConstraint:0x1c0c8a320 V:[form-view]-(0)-[profiles-view] (active, names: profiles-view:0x106ccd430, form-view:0x10ed307c0)>", 
    "<NSLayoutConstraint:0x1c4c80af0 V:[_UILayoutGuide:0x106ccf4e0]-(10)-[UILabel:0x106ccf070'Completa tu Perfil'] (active)>", 
    "<NSLayoutConstraint:0x1c4c80cd0 V:[UILabel:0x106ccf070'Completa tu Perfil']-(8)-[UIImageView:0x106cce6c0] (active)>", 
    "<NSLayoutConstraint:0x1c4c80d20 V:[UIImageView:0x106cce6c0]-(0)-[UIScrollView:0x107a37000] (active)>", 
    "<NSLayoutConstraint:0x1c4c80e10 UIImageView:0x106ccddf0.top == profiles-view.top (active, names: profiles-view:0x106ccd430)>", 
    "<NSLayoutConstraint:0x1c4c80f00 V:[UIImageView:0x106ccddf0]-(0)-[_UILayoutGuide:0x106ccf6d0] (active)>", 
    "<NSLayoutConstraint:0x1c0c8bdb0 'UIView-Encapsulated-Layout-Height' UIView:0x106ccdc10.height == 667 (active)>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1c0c886b0 form-view.height == 579 (active, names: form-view:0x10ed307c0)> 

Ainsi, puisque la contrainte de hauteur a été brisée, AutoLayout organiser les éléments suivants les contraintes de marge qui permet aux vues ont éclaté de cette façon.

Cela dit, la façon dont j'ajoute les contraintes est la suivante:

func addModelButtonAction(_ sender: Any) { // an IBAction 
    addButton.isHighlighted = false 
    let last = modelTextFields.last! 
    let textField = last.createCopy() // extension method for creating a copy of the last textField 
    modelTextFieldsView.insertSubview(textField, belowSubview: last) 
    let growth = last.frame.height + 8 // the 8 represents the top spacing between textFields 
    formViewHeight.constant += growth // increasing height of the view where the form is embeded 
    modelTextFieldsHeight.constant += growth // increasing height of the view where the textFields are embeded 
    UIView.animate(withDuration: 0.5) { 
     self.view.layoutIfNeeded() 
     textField.frame.origin.y += growth // moving new textField below the previous one 
    } 

    modelTextFields.append(textField) // array of UITextField to keep track of the textFields in screen 
} 

Et les rectangles d'alignement de la vue: view-rectangles

Et la hiérarchie de la vue:

view-hierarchy

Que puis-je faire pour que cela fonctionne comme prévu? J'apprécie votre aide dans ce domaine, parce que j'ai essayé de comprendre cela sans succès.

Merci d'avance!

Répondre

2

Vous avez deux options pour résoudre ce problème de mise en page:

Personnellement, je pourrais essayer intégrer ces vues dans un UIStackView. La vue de la pile va travailler pour gérer la disposition verticale pour vous, vous permettant d'insérer et supprimer des sous-vues au besoin. UIStackView est particulièrement facile à utiliser avec Interface Builder si vous utilisez des Storyboards.

Vous pouvez également utiliser un UITableView pour cette mise en page; il gèrerait le flux vertical en votre nom, en faisant abstraction de la plupart des maux de tête liés à la mise en page, bien que vous deviez gérer vous-même la source de données et les cellules.

Vous pouvez probablement faire en sorte que cette disposition fonctionne sans l'un ou l'autre de ces éléments en gérant soigneusement la priorité des différentes contraintes, ce qui permet de les casser lorsque la disposition change, mais cela peut être fastidieux.

+0

L'utilisation de 'UIStackView' était intelligente. Merci beaucoup!! –

+0

@ AbrahamDurán Sure chose! N'oubliez pas, vous pouvez ajouter et supprimer les sous-vues gérées de la vue de la pile dans un bloc d'animation UIView et cela va bien animer ces changements! –