简体   繁体   中英

Changing Constraints Programmatically

I have a user form where there are a bunch of Label and its corresponding text field or drop down or checkbox group arranged vertically on Storyboard. Something like this:

Label 1
   Text Field 1
Label 2
   Check Box Group
Label 3
   Drop Down Field
Label 4
   Text Field 4

Under normal condition, constraint set up between Labels is 60 vertically.

The problem is since Check Box Group is dynamically populated from the data retrieved from server, I don't know how many checkboxes will be there between Label 2 and Label 3 at StoryBoard design time. So there comes a need to programmatically change the constraint between Label 2 and Label 3.

Currently, what I did was set constraint 60 between them but check "Remove at build time" and programmatically set the constraint depending on how many checkboxes are there between there. Something like this:

[_superView addConstraint:[NSLayoutConstraint constraintWithItem:_Label3 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_Label2 attribute:NSLayoutAttributeBottom multiplier:1 constant:100]];

But for some reasons , this is not working as expected. Although Label3 is correctly placed after the last checkbox, I could only see half of the Label4 which has height constraint. I tried:

[superView updateConstraints];
[superView layoutIfNeeded];

But to no avail.

You can add vertical spacing constraint in storyboard, and add an nslayoutconstraint iboutlet var in view controller and connect the same to the constraint in storyboard.

Now the constraint.constant value can be changed programmatically to whatever value you want to instead of adding it.

Personally, I'd be inclined to not have any constraints between "Label 1", "Label 2", etc. I would instead create a view with container views that will contain the various fields between the labels:

在此处输入图片说明

I'd define vertical constraints like so (I'm assuming you'd do this in storyboard, like I did above, but I'm showing example VFL as that's a concise and precise way of describing a whole set of vertical constraints):

V:|-[label1]-[group1(0@250)]-[label2]-[group2(0@250)]-[label3]-[group3(0@250)]-[label4]-[group4(0@250)]-|"

Note, in my snapshot, I gave those container "group" views a non-zero height and a gray background, so you can see them, but hopefully this illustrates the idea. Have placeholder views that will contain the controls underneath the various labels and give that a zero height but a low (250) priority (or, like you did, have it omit them at run time).

Then you can programmatically add whatever controls you want as subviews of their respective group views as set their constraints accordingly, eg

V:|-[MoView]-[LarryView]-[CurlyView]-|

And because those have a higher prior than the zero height constraints of the group boxes, the resulting view will be resized accordingly, eg:

在此处输入图片说明

You can probably accomplish something very similar using UIStackView (if targeting iOS 9 and later), but if using simple constraints, this is how I'd tackle it.

That way, you get out of the business of coding magical spaces between "Label 1" and "Label 2", which will become invalid if, for example, you change fonts at some future date (or better, support the use of the user-provided font sizes specified within the Settings app).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM