Saturday, 17 August 2013

Autolayout, programed vs interface builder

Autolayout, programed vs interface builder

Just to add a view that lives in the same parent view as the other two
related views.
self.vDist = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 42, 21)];
[self.vDist setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:self.vDist];
NSLayoutConstraint *lc;
lc = [NSLayoutConstraint constraintWithItem:self.vDist
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0
constant:20.0];
[self.view addConstraint:lc];
lc = [NSLayoutConstraint constraintWithItem:self.vDist
attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0
constant:20.0];
[self.view addConstraint:lc];
Then, I create the small squared view on top
/*********************** video view */
self.videoView = [[UIView alloc] initWithFrame:CGRectMake(90, 20, 140, 140)];
[self.videoView setBackgroundColor:[UIColor greenColor]];
[self.videoView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:self.videoView];
// width & height constraints, as UIViews don't have intrinsic constraints
lc = [NSLayoutConstraint constraintWithItem:self.videoView
attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual
toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0
constant:140.0];
[self.videoView addConstraint:lc];
lc = [NSLayoutConstraint constraintWithItem:self.videoView
attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual
toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0
constant:140.0];
[self.videoView addConstraint:lc];
// center constraint
lc = [NSLayoutConstraint constraintWithItem:self.videoView
attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0
constant:0.0];
[self.view addConstraint:lc];
// top constraint with its parent view
lc = [NSLayoutConstraint constraintWithItem:self.videoView
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0
constant:20.0];
[self.view addConstraint:lc];
This squared view shows ok in any device orientation
Now I create the second view on the lower part of the screen. It really
doesn't matter its dimensions here as I create a constraint for each size
attribute
/*********************** listado view */
self.listadoView = [[UIView alloc] initWithFrame:CGRectMake(5, 248, 310,
100)];
[self.listadoView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.listadoView setBackgroundColor:[UIColor whiteColor]];
[self.view addSubview:self.listadoView];
// height and width constraints as UIView don't have intrinsic constraints
lc = [NSLayoutConstraint constraintWithItem:self.listadoView
attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual
toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0
constant:310];
[self.listadoView addConstraint:lc];
lc = [NSLayoutConstraint constraintWithItem:self.listadoView
attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual
toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0
constant:300];
// make it weak to be able to squeeze contents
lc.priority = 250;
[self.listadoView addConstraint:lc];
// top with videoView's bottom
lc = [NSLayoutConstraint constraintWithItem:self.listadoView
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationLessThanOrEqual
toItem:self.videoView attribute:NSLayoutAttributeBottom multiplier:1.0
constant:88.0];
[self.view addConstraint:lc];
// top with parent's view top
lc = [NSLayoutConstraint constraintWithItem:self.listadoView
attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0
constant:248.0];
[self.view addConstraint:lc];
// center constraint
lc = [NSLayoutConstraint constraintWithItem:self.listadoView
attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0
constant:0.0];
[self.view addConstraint:lc];
trying to replicate here what IB did with the constraints in the other view
lc = [NSLayoutConstraint constraintWithItem:self.listadoView
attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0
constant:5];
[self.view addConstraint:lc];
lc = [NSLayoutConstraint constraintWithItem:self.listadoView
attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual
toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0
constant:10];
[self.view addConstraint:lc];
Te resulting screens are below with the green square. The vertical green
screen shows what I was expecting (see yellow images down below), but in
the green horizontal, as you can see, the bottom edge of the listadoView
is below the edge of the screen, even though I'm setting all the
constraints IB sets for the yellow one, those along with the ones I set in
the yellow one too.
Any advice on how to set the constraints?... maybe the order in which they
are created has something to do with it?, because there were times when I
removed a constraint and it worked, then I re-added that constraint and
still worked!. Ran it again with all the constraints, and then stopped
working (what?!). And it's been hard to successfully reproduce it in order
to file a bug, but it happened.
I've tested this code in XCode 4.6 under iOS5.1 and 6.x and with xCode 5
under iOS6.1.

No comments:

Post a Comment